Nested Promise execution is out of sync

半腔热情 提交于 2019-12-11 09:17:10

问题


I have a simple setup, illustrated in 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!');
    });

The output is:

a done2
b done2
all done!
a done
b done

But I expect:

a done
b done
a done2
b done2
all done!

What am I doing wrong?


回答1:


As Bergi points out, it's not valid to pass a promise as the argument to then, but even if it were allowed, another issue is that as soon as you call delayMany('a'), the Promise.delay(50) inside it will start executing which is not what you are looking to do.

You can either wrap the call in an anonymous function, or use .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!');
});

Q: "Why doesn't then throw an error when I pass a promise to it?"

The answer to this is in the Promises/A+ spec:

A promise’s then method accepts two arguments:

promise.then(onFulfilled, onRejected)

2.2.1. Both onFulfilled and onRejected are optional arguments:

2.2.1.1. If onFulfilled is not a function, it must be ignored.




回答2:


You must not pass a promise (the result of immediately calling delayMany) to then. Instead, it expects a callback function to execute when the context promise resolves. You'll need to wrap your delayMany invocation in a function expression:

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!'); });



回答3:


Since you are using bluebird you can simply use the .delay method instead:

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!');
    });


来源:https://stackoverflow.com/questions/27985332/nested-promise-execution-is-out-of-sync

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!