最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Why are Javascript promises resolving out of order? - Stack Overflow

programmeradmin1浏览0评论

I am attempting to use JavaScript promises in a project and the order of events are unexpected. I have narrowed it down into a small demo using a test promise.

testPromises = function(promiseNum){
    return new Promise(function(resolve, reject) {
        console.log ('handling promise '+promiseNum);
        setTimeout(function(){
            console.log("resolving testPromises "+promiseNum);
            resolve();
        },2000)
    });
};

And then I call it like so:

testPromises(1).then(testPromises(2)).then(testPromises(3))
.then(function(value) {
        console.log('all promises resolved');
}, function(reason) {
        console.log('some promise was rejected');
});

This is the console output:

handling promise 1
handling promise 2
handling promise 3
resolving testPromises 1
all promises resolved
resolving testPromises 2
resolving testPromises 3

How can I get an output of:

handling promise 1
resolving testPromises 1
handling promise 2
resolving testPromises 2
handling promise 3
resolving testPromises 3
all promises resolved

I am attempting to use JavaScript promises in a project and the order of events are unexpected. I have narrowed it down into a small demo using a test promise.

testPromises = function(promiseNum){
    return new Promise(function(resolve, reject) {
        console.log ('handling promise '+promiseNum);
        setTimeout(function(){
            console.log("resolving testPromises "+promiseNum);
            resolve();
        },2000)
    });
};

And then I call it like so:

testPromises(1).then(testPromises(2)).then(testPromises(3))
.then(function(value) {
        console.log('all promises resolved');
}, function(reason) {
        console.log('some promise was rejected');
});

This is the console output:

handling promise 1
handling promise 2
handling promise 3
resolving testPromises 1
all promises resolved
resolving testPromises 2
resolving testPromises 3

How can I get an output of:

handling promise 1
resolving testPromises 1
handling promise 2
resolving testPromises 2
handling promise 3
resolving testPromises 3
all promises resolved
Share Improve this question asked Oct 24, 2016 at 22:00 amaackamaack 961 silver badge8 bronze badges 1
  • 1 Like @jacub.g has pointed out all your promises have all been created before the then function is even called. A nice solution for this type of promise looping is to use a helper function. Bluebird has a map function that has a concurrency option, in this case you could set this to 1. – Keith Commented Oct 24, 2016 at 22:21
Add a ment  | 

3 Answers 3

Reset to default 9

.then() expects a function reference. When you do something like this:

.then(testPromises(2))

you are executing the function testPromise() immediately and passing the return value to .then(). This is almost never what you want (unless testPromises() returned another function) because for .then() to do its job, you MUST pass it a function reference (a function that it can call sometime later). If you execute the function immediately, then .then() can't do its job and call it LATER.

Instead, what you want is this:

.then(function() {
    return testPromises(2);
})

Or, you could use .bind():

.then(testPromises.bind(null, 2))

So, your whole chain would look like this:

testPromises(1).then(function() {
    return testPromises(2);
}).then(function() {
    return testPromises(3);
}).then(function(value) {
    console.log('all promises resolved');
}, function(reason) {
    console.log('some promise was rejected');
});

Or, using .bind()

testPromises(1)
  .then(testPromises.bind(null, 2))
  .then(testPromises.bind(null, 3))
  .then(function(value) {
        console.log('all promises resolved');
  }, function(reason) {
        console.log('some promise was rejected');
  });

If you're doing this a lot, you could make a curry wrapper for testPromises() that would return another function. This is essentially what .bind() above was doing, but the syntax is a little prettier to use once you've declared your wrapper function.

function tp(arg) {
    return function() {
        return testPromises(arg);
    }
}

Then, because that wrapper returns another function, you could then do:

testPromises(1).then(tp(2)).then(tp(3))
.then(function(value) {
    console.log('all promises resolved');
}, function(reason) {
    console.log('some promise was rejected');
});

This is the code to get the output you want:

testPromises(1).then(function(){
  return testPromises(2);
}).then(function(){
  return testPromises(3);
}).then(function(value) {
  console.log('all promises resolved');
}, function(reason) {
  console.log('some promise was rejected');
});

Promises are resolved asynchronously, but created synchronously.

testPromises(1).then(testPromises(2)).then(testPromises(3))

is more or less like doing

p1 = testPromises(1)
p2 = testPromises(2)
p3 = testPromises(3)

p1.then(p2).then(p3)

Since new Promise is synchronous, the first 3 lines you'll see will be

handling promise 1
handling promise 2
handling promise 3

Well,

handling promise 1
handling promise 2
handling promise 3

occurs first because these calls are independent from the Promise workflow, they are executed right when you create each Promise object, because to do that you explicit execute each function like testPromises(1) and so on.

But the problem is that your call to console.log('all promises resolved'); depends only on testPromises(1) being resolved, all your other promises are detached.

In order do sync them, each .then call have to return a Promise, and you can do it by using a function and returning the Promises testPromises function already returns.

testPromises = function(promiseNum){
    return new Promise(function(resolve, reject) {
        console.log ('handling promise '+promiseNum);
        setTimeout(function(){
            console.log("resolving testPromises "+promiseNum);
            resolve();
        },0)
    });
};

testPromises(1).then(function() {
  return testPromises(2);
}).then(function() {
  return testPromises(3);
}).then(function(value) {
        console.log('all promises resolved');
}, function(reason) {
        console.log('some promise was rejected');
});

发布评论

评论列表(0)

  1. 暂无评论