2

I am trying to do a for loop in a promise but unfortunatly the output that comes out it is not what i am expecting:

My code

    var ahaha = function mytestfunction(numb){
    return  new Promise(function(resolve, reject) {
        console.log(numb);
        return resolve('test');
    })
    .then(function(x) {
    z='firststep' + x ;
    console.log(z);
    return z; 
    })
    .then(function(z) {
    console.log(z + 'secondstep');
    return z
    })
    .then(function(z) {
    console.log(z + 'thirdstep')
    });
};

var promises = [];
    for (var i = 1; i <= 2; i++) {
       promises.push(ahaha(i));
    }

Promise.all(promises)    
 .then(function(data){ console.log("everything is finished")});

What it returns is :

1
2
firststeptest
firststeptest
firststeptestsecondstep
firststeptestsecondstep
firststeptestthirdstep
firststeptestthirdstep
everything is finished

But i want it to return

1
firststeptest
firststeptestsecondstep
firststeptestthirdstep
2
firststeptest
firststeptestsecondstep
firststeptestthirdstep
everything is finished

I don't understand why the promises are not chained one after the other one.

Note that i succeed doing this operation using async.waterfall but i also want to know how to do it with promises.

Thanks a lot

patrick
  • 374
  • 2
  • 17

2 Answers2

2

Promise.all() is purposely used when you want things to run in parallel and it will tell you when all are done and they may each finish in any order.

There are lots of different ways to sequence things using promises. If you just have two function calls like your code shows, you can just do them manually:

ahaha(1).then(result => ahaha(2)).then(data => {
    console.log("everything finished");
});

Or, a common pattern using .reduce():

[1,2].reduce(p, val => {
    return p.then(() => ahaha(val));
}, Promise.resolve()).then(data => {
    // everything done here
});

Or, my favorite using the Bluebird promise library:

Promise.mapSeries([1,2], ahaha).then(result => {
    // everything done here
});

There are many other schemes, which you can see in these other answers:

How to synchronize a sequence of promises?

JavaScript: Perform a chain of promises synchronously

ES6 Promises - something like async.each?

How can I execute shell commands in sequence?

Can Promise load multi urls in order?

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
1

Promise.all is used to run the promises in parallel, not sequentially.

Using the popular BlueBird library, you could have used reduce but there's no equivalent function in standard ES6 but you can do this:

promises.reduce(
    (p, next) => p.then(next),
    Promise.resolve()
).then(data=>{ console.log("everything is finished")});
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758