Hacker News new | past | comments | ask | show | jobs | submit login
Are you serial, Promise.all? (bramanti.me)
1 point by jadengore on March 4, 2016 | hide | past | favorite | 6 comments

When you actually look at the code, and how you're executing the functions, it makes sense that Promise.all doesn't magically make your promises run in serial.

      knex.schema.renameTable('tomatoes', 'potatoes'),
      knex.schema.table('potatoes', (table) => table.string('name'))
Promise.all doesn't execute the functions - you're doing that yourself. The argument you're passing to Promise.all is just an array of already kicked-off promises. Consider it rewritten as:

    const promise1 = knex.schema.renameTable('tomatoes', 'potatoes’);
    const promise2 = knex.schema.table('potatoes', (table) => table.string('name’));
    Promise.all([promise1, promise2]);
Promise.all is just create a new Promise for you that is resolved when the promises you pass in are all resolved.

In fact, looking at the 'solution' to this (Promise.series), it still suffers from the same problem. See this demo of it still not working https://tonicdev.com/56da37cb0ba4470d00919c26/56da37cb0ba447...

Awesome find! I was not considering that a promise is executing as soon as it is created, and this is why the implementation still results in parallel execution.

I've gone back to the drawing board, and I've updated my post accordingly with a better solution using reduce. I've also used your demo above as an example and credited you in my article (please let me know if that is not OK, and I will take it down).

Thanks again!

The canonical way to execute a collection of promises serially is through Array.prototype.reduce:

  let finalResult = promises.reduce((current, next) => current.then(next), Promise.resolve());
(I've used ES6 syntax, but you can do this in ES5.1 as well. You can also substitute Promise.prototype.then.call for the arrow function.)

The beauty of this one-liner is that it works with any promise-like object: you don't need to use BlueBird, you don't even need to use a uniform promise implementation, it'll work with anything that follows the Promises/A+ spec.

This is cool! Thanks for sharing!

In my case, there is a bit less code, but I really do appreciate how your implementation is not Bluebird-dependent.

I believe promise.each is not serial in the way you think it is. Promises do handle only the resolution of certain events. So in your example both statements are executed exactly at the time you set up your array of promises. Promises.each then only ensures that their promise handlers are executed in sequence.

So instead of promises you could create an array of arrow functions and with promise.each execute one after the other.

I've come up with a similar implementation, I will credit you for inspiring a working solution in my article! Thank you very much!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact