for promise on promise不遵循良好的输出顺序

时间:2017-01-13 09:45:06

标签: node.js promise ecmascript-6

我正在尝试在一个承诺中做一个for循环,但不幸的是它出来的输出并不是我所期待的:

我的代码

    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")});

它返回的是:

1
2
firststeptest
firststeptest
firststeptestsecondstep
firststeptestsecondstep
firststeptestthirdstep
firststeptestthirdstep
everything is finished

但我希望它返回

1
firststeptest
firststeptestsecondstep
firststeptestthirdstep
2
firststeptest
firststeptestsecondstep
firststeptestthirdstep
everything is finished

我不明白为什么承诺不会一个接一个地链接。

请注意,我使用async.waterfall成功执行此操作,但我也想知道如何使用promises。

非常感谢

2 个答案:

答案 0 :(得分:2)

Promise.all()是有意使用的,当你想要并行运行时它会告诉你什么时候完成它们并且每个都可以按任何顺序完成。

使用promises对事物进行排序的方法有很多种。如果您只有两个函数调用,如代码显示,您可以手动执行:

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

或者,使用.reduce()的常见模式:

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

或者,我最喜欢使用Bluebird promise库:

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

还有许多其他方案,您可以在其他答案中看到:

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?

答案 1 :(得分:1)

Promise.all用于并行运行promises,而不是顺序运行。

使用流行的BlueBird库,您可以使用reduce,但标准ES6中没有等效功能,但您可以这样做:

promises.reduce(
    (p, next) => p.then(next),
    Promise.resolve()
).then(data=>{ console.log("everything is finished")});