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