To tick or not to tick?
See original GitHub issue- What version of bluebird is the issue happening on?
v3.5.1
- What platform and version? (For example Node.js 0.12 or Google Chrome 32)
Node v6.12.2, Mac OS 10.12.6
- Did this issue happen with earlier version of bluebird?
Not sure.
I was interested by @benjamingr’s comment on https://github.com/nodejs/promises/issues/31#issuecomment-322744586 stating that Bluebird avoids an extra tick before calling a .then()
handler if the promise it’s chained onto has already taken a tick to resolve.
new Promise(r => setTimeout(r, 1)).then(x => console.log("Got here"))
In this case, bluebird sees that new Promise did not resolve synchronously and thus does not defer the console.log to the next tick (it was already deferred). It also does this optimization when promisifying.
Here is an example which seems to demonstrate the opposite:
const Promise = require('bluebird');
let resolve;
const p = new Promise( r => resolve = r );
p.then( () => console.log('then handler called') );
setTimeout( () => {
console.log('resolving');
resolve();
console.log('resolved');
}, 1000 );
The promise is resolved asynchronously, and many ticks after .then()
is called. So, if I understood what @benjamingr was saying right, I’d have expected the then handler to be called synchronously when the promise is resolved. But it’s not. The output is:
resolving
resolved
then handler called
I also can’t see a call to ._setAsyncGuaranteed()
anywhere on the code path for the Promise constructor - which as far as I can see is what would prevent an additional tick being introduced.
Promise.promisify()
, however, does achieve this optimisation:
let resolve;
const f = Promise.promisify( cb => resolve = cb );
const p = f();
p.then( () => console.log('then handler called') );
setTimeout(() => {
console.log('resolving');
resolve();
console.log('resolved');
}, 1000);
outputs:
resolving
then handler called
resolved
Did I miss the point here?
Issue Analytics
- State:
- Created 6 years ago
- Comments:13 (5 by maintainers)
@domenic Just to throw my view in… Yes, I believe in the example I gave in https://github.com/petkaantonov/bluebird/issues/1498#issuecomment-361968637 does demonstrate bluebird optimizing too aggressively in this case.
But in my opinion that’s an implementation error in bluebird in this specific edge case. I did not meant to discredit the optimization overall. I can see many other cases where this optimization can be applied and, as you say, there’d be no test which could identify whether the optimization had been used or not.
Am on the hop so can’t write more at present but will try to find some time to write a more thorough explanation later.
Promisify and promisifyAll are custom APIs that are not specced. The idea is that anything you would promisify is asynchronous anyway, so why produce further delays? It should only be observable when something you promisify is actually synchonous, as you noticed.