I have an array of promises that need to run in sequential order.
var promises = [promise1, promise2, ..., promiseN];
Calling RSVP.all will execute them in parallel:
RSVP.all(promises).then(...);
But, how can I run them in sequence?
I can manually stack them like this
RSVP.resolve()
.then(promise1)
.then(promise2)
...
.then(promiseN)
.then(...);
but the problem is that the number of promises varies and array of promises is built dynamically.
All is needed to solve that is a
for
loop :)I'm going to leave this answer here because this would have helped me when I came looking here for a solution to my problem.
The thing I was after was essentially mapSeries... and I happen to be mapping save over a set of values... and I want the results...
So, here's as far as I got, FWIW, to help others searching for similar things in the future....
(Note that the context is an ember app)
I had similar problem, and I made a recursive function which runs functions one by one sequentially.
In case you need to collect output from these functions:
ES7 way in 2017.
This will execute the given functions sequentially(one by one), not in parallel. The parameter
promises
is an array of functions, which returnPromise
.Plunker example with the above code: http://plnkr.co/edit/UP0rhD?p=preview
A second attempt at an answer in which I try to be more explanatory:
First, some requisite background, from the RSVP README:
This is precisely how you make promises sequential, by returning the later promise from the
then
of the promise that should finish before it.It is helpful to think of such a set of promises as a tree, where the branches represent sequential processes, and the leaves represent concurrent processes.
The process of building up such a tree of promises is analogous to the very common task of building other sorts of trees: maintain a pointer or reference to where in the tree you are currently adding branches, and iteratively add things.
As @Esailija pointed out in his answer, if you have an array of promise-returning functions that don't take arguments you can use
reduce
to neatly build the tree for you. If you've ever implemented reduce for yourself, you will understand that what reduce is doing behind the scenes in @Esailija's answer is maintaining a reference to the current promise (cur
) and having each promise return the next promise in itsthen
.If you DON'T have a nice array of homogeneous (with respect to the arguments they take/return) promise returning functions, or if you need a more complicated structure than a simple linear sequence, you can construct the tree of promises yourself by maintaining a reference to the position in the promise tree where you want to add new promises:
You can build combinations of concurrent and sequential processes by using RSVP.all to add multiple "leaves" to a promise "branch". My downvoted-for-being-too-complicated answer shows an example of that.
You can also use Ember.run.scheduleOnce('afterRender') to ensure that something done in one promise gets rendered before the next promise is fired -- my downvoted-for-being-too-complicated answer also shows an example of that.
If you already have them in an array then they are already executing. If you have a promise then it's already executing. This is not a concern of promises (I.E they are not like C#
Task
s in that regard with.Start()
method)..all
doesn't execute anything it just returns a promise.If you have an array of promise returning functions:
Or values: