嵌套的Promise执行不同步

时间:2015-01-16 13:45:22

标签: javascript asynchronous promise bluebird

我有一个简单的设置,如this fiddle所示:

var doDelay = function(who) {
    return Promise.delay(50)
        .tap(function() {
            console.log(who + ' done');
        });
};

Promise.resolve()
    .then(doDelay('a'))
    .tap(function() {
        console.log('a done2');
    })
    .then(doDelay('b'))
    .tap(function() {
        console.log('b done2');
    })
    .then(function() {
        console.log('all done!');
    });

输出结果为:

a done2
b done2
all done!
a done
b done

但我希望:

a done
b done
a done2
b done2
all done!

我做错了什么?

3 个答案:

答案 0 :(得分:2)

您不得将承诺(即调用 delayMany的结果)传递给then。相反,它希望在上下文保证解析时执行回调函数。您需要将delayMany调用包装在函数表达式中:

Promise.resolve()
.then(function(undefined) { return delayMany(xsa); })
.tap(function(xsa) { console.log(xsa[0] + ' done2'); })
.then(function(xsa) { return delayMany(xsb) })
.tap(function(xsb) { console.log(xsb[0] + ' done2'); })
.then(function(xsb) { console.log('all done!'); });

答案 1 :(得分:2)

正如Bergi所指出的那样,将一个承诺作为then的参数传递是无效的,但即使它被允许,另一个问题是,只要你调用delayMany('a'),{{{} 1}}它将开始执行,这不是你想要做的。

您可以使用匿名函数包装调用,也可以使用Promise.delay(50)

.bind()

问:“当我向其传递承诺时,为什么var delayMany = function(who) { return Promise.delay(50) .tap(function() { console.log(who + ' done'); }); }; Promise.resolve() .then(delayMany.bind(null, 'a')) .tap(function() { console.log('a done2'); }) .then(delayMany.bind(null, 'b')) .tap(function() { console.log('b done2'); }) .then(function() { console.log('all done!'); }); 不会抛出错误?”

答案是Promises/A+ spec

  

promise的then方法接受两个参数:

     

then

     

2.2.1。 promise.then(onFulfilled, onRejected)onFulfilled都是可选参数:

     

2.2.1.1。 如果onRejected不是函数,则必须忽略它。

答案 2 :(得分:1)

由于您使用蓝鸟,您只需使用.delay方法:

Promise.resolve()
    .delay('a', 50)
    .tap(function() {
        console.log('a done2');
    })
    .delay('b', 50)
    .tap(function() {
        console.log('b done2');
    })
    .then(function() {
        console.log('all done!');
    });