How can I sequentially chain promises using bluebirdjs?
Asked Answered
P

2

8

Promise.all() doesn't guarantee that promises will be resolved in order. How can this be done?

Pinochle answered 16/8, 2014 at 8:23 Comment(0)
Q
8

Since you're using Bluebird JS, this can be actually done in a simple way.

In version 2.0, Bluebird introduced the Promise.each method that does this, for looping a then is simple enough, but since it is so common and got requested time after time eventually it was added as its own method.

function foo(item, ms){ // note bluebird has a delay method
    return Promise.delay(ms, item).then(console.log.bind(console))
}

var items = ['one', 'two', 'three'];

Promise.each(items, function(item, i){
    return foo(item, (items.length - i) * 1000)
});

Which produces the same result as the other answer, only with less lines of code and it also lets Bluebird perform optimizations on the iteration.

Quiescent answered 16/8, 2014 at 8:32 Comment(0)
P
0

The thing that confused me most is that the async function being chained needs to return a function that returns a promise. Here's an example:

function setTimeoutPromise(ms) {
  return new Promise(function (resolve) {
    setTimeout(resolve, ms);
  });
}

function foo(item, ms) {
  return function() {
    return setTimeoutPromise(ms).then(function () {
      console.log(item);
    });
  };
}

var items = ['one', 'two', 'three'];

function bar() {
  var chain = Promise.resolve();
  items.forEach(function (el, i) {
    chain = chain.then(foo(el, (items.length - i)*1000));
  });
  return chain;
}

bar().then(function () {
  console.log('done');
});

Notice that foo returns a function that returns a promise. foo() does not return a promise directly.

See this Live Demo

Pinochle answered 16/8, 2014 at 8:23 Comment(6)
Why are you returning a chain.then() when then() is called like that it effectively doesn't do anything but copy the promise.Quiescent
Benjamin's example is definitely simpler. I developed mine as I was dealing with the lie promise lib (github.com/calvinmetcalf/lie) in pouchdb in which case there isn't support for the each() call. My question should really have referenced liejs and not bluebirdjs :).Pinochle
@BenjaminGruenbaum how else would you chain these promises using my code? I'm still learning the nuances of promises, so I'd appreciate your input.Pinochle
return chain instead of return chain.then()Quiescent
Yup, missed that one :)Pinochle
Also, for .. in loops do not guarantee iteration order, this can be result in an incorrect order in your case, you can use items.forEach or for(var i = 0;... insteadQuiescent

© 2022 - 2024 — McMap. All rights reserved.