-2

I have the following node.js code:

var params = initDbParams();
query().then(orders => function(){
  return match(orders);
}).then(() => function(){
  return place();
}).catch(err => {
  console.log("Error");
});


function initDbParams() {
  console.log("initDbParams Start");
  var a = 1;
  var b = 2;
  var c = 3;
  console.log("initDbParams End");
  return a+b+c;
}

function update() {
  return new Promise(function(resolve, reject ){
    console.log("update Start");
    setTimeout(function(){
        console.log("update timeout over");
    }, 1000);
    console.log("update End");
    resolve();
  });
}

function del() {
  return new Promise(function(resolve, reject ){
    console.log("delete Start");
    setTimeout(function(){
        console.log("del timeout over");
    }, 1200);
    console.log("delete End");
    resolve();
  });
}

function place() {
  return new Promise(function(resolve, reject ){
    console.log("place Start");
    setTimeout(function(){
        console.log("place timeout over");
    }, 1500);
    console.log("place End");
    resolve();
  });
}

function write() {
  return new Promise(function(resolve, reject ){
    console.log("write Start");
    setTimeout(function(){
        console.log("write timeout over");
    }, 2000);
    console.log("write End");
    resolve();
  });
}

function query() {
  return new Promise(function(resolve, reject ){
    console.log("query Start");
    setTimeout(function(){
        console.log("query timeout over");
    }, 3000);
    var orders = [12,24,25,100];
    console.log("query End");
    resolve(orders);
  });
}

function match(orders) {
  return new Promise(function(resolve, reject ){
    console.log("match Start");
    while(orders.length !== 0)
    {
      var order = orders.shift();
      del().then(() => {
        write();
      })
    }
    console.log("match End");
    resolve();
  });
}

I get the following output:

  1. initDbParams Start
  2. initDbParams End
  3. query Start
  4. query End

I would expect the following output:

  1. initDbParams Start
  2. initDbParams End
  3. query Start
  4. query timeout over
  5. query End
  6. match Start
    1. del Start
    2. del End
    3. write Start
    4. write End
  7. match End

What do I Need to change to get the expected results? Thanks for your support!

Homer
  • 239
  • 2
  • 11
  • in your `setTimeout`s, make sure the resolve is inside the callback, otherwise, it will only put the console.log later but will resolve immediately without waiting for the timeout to finish – casraf Feb 25 '18 at 13:59
  • Thanks for that hint: Now I get: 1. initDbParams Start 2. initDbParams End 3. query Start 4. query timeout over 5. query End Still no call of match and place. – Homer Feb 25 '18 at 14:12

1 Answers1

0

setTimeout is still asynchronous, and being called inside a promise doesn't change that. All your timeout over logs will happen later, while the code immediately continues to log end and resolve the promise. You need to call resolve in the asynchronous callback! Same thing in match, where you should also avoid the Promise constructor antipattern.

It should look like this:

function delay(t) {
  return new Promise(function(resolve) {
    setTimeout(function() {
      console.log("timeout over");
      resolve(); // in here!
    }, t);
  });
}

You can then reuse that function to avoid repeating yourself:

function update() {
  console.log("update Start");
  return delay(1000).then(function(){
    console.log("update End");
  });
}

function del() {
  console.log("delete Start");
  return delay(1200).then(function() {
    console.log("delete End");
  });
}

function place() {
  console.log("place Start");
  return delay(1500).then(function() {
    console.log("place End");
  });
}

function write() {
  console.log("write Start");
  return delay(2000).then(function() {
    console.log("write End");
  });
}

function query() {
  console.log("query Start");
  return delay(3000).then(function() {
    var orders = [12,24,25,100];
    console.log("query End");
    return orders;
  });
}

function match(orders) {
  console.log("match Start");
  var promises = orders.map(function(order) {
    return del().then(write);
  });
  return Promise.all(promises).then(function() {
    console.log("match End");
  });
}

Also, .then(orders => function(){ … }) doesn't make sense. It should be either

query().then(function(orders) {
  return match(orders);
}).then(function() {
  return place();
}).catch(err => {
  console.log("Error");
});

or

query().then(orders => 
  match(orders)
).then(() =>
  place()
).catch(err => {
  console.log("Error");
});

but not both an arrow function and a function expression.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thank you very much, Bergi, for your proposal. If I leave the call block {query().then(orders => function(){ return match(orders); }).then(() => function(){ return place(); }).catch(err => { console.log("Error"); });} as is, query is called and processed in correct sequence, however, match() seems not to be called. – Homer Feb 25 '18 at 16:10
  • @Homer Ah, that code looked correct on the first glance, but actually you're returning a function from the promise callback and never call `match` in there. Updated my answer. – Bergi Feb 25 '18 at 16:35
  • Thank you very much. Now it looks somehow better, however still not as expected: initDbParams Start initDbParams End query Start timeout over query End match Start delete Start delete Start delete Start delete Start timeout over delete End write Start timeout over delete End write Start timeout over delete End write Start timeout over delete End write Start timeout over write End timeout over timeout over write End write End timeout over write End match End place Start timeout over place End – Homer Feb 25 '18 at 16:46
  • In the `matcher()` I expected the sequence "delete start"/"delete end" "write start"/"write end" "delete start"/"delete end" "write start"/"write end", etc. – Homer Feb 25 '18 at 16:55
  • For sequential execution, you'd use `function match(orders) { return orders.reduce(function(chain, order) { return chain.then(del).then(write); }, Promise.resolve()); }`, but I don't see what's wrong with doing it concurrently. – Bergi Feb 25 '18 at 16:58
  • Perfect! Everything runs as expected! Thank you very much for your support! A write can only be conducted after a successful delete. That is a requirement. – Homer Feb 26 '18 at 16:42