-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
Description
While going through some examples I ran into the following buggy behavior in async_hooks. Promise callbacks don't seem to have context by default. Even more surprisingly Adding a dummy init makes the context appears as if by magic!
I intend to look at this in detail later, but opening the issue now in case someone else wants to take a peek.
const ah = require('async_hooks');
let hooks;
switch (process.argv[2]) {
default:
console.log('run this test with a numeric argument');
process.exit(1);
case '1':
hooks = {}; // no hooks
break;
case '2':
hooks = { init() {} }; // empty init hook
break;
}
ah.createHook(hooks).enable();
Promise.resolve(1729).then(() => {
console.log(`then callback ran with eid ${ah.executionAsyncId()} tid ${ah.triggerAsyncId()}`);
});
Unlike timers, and other Node.js async APIs (e.g. fs.read), by default the triggerAsyncId
is always 0 (i.e. missing context) inside the then
callback. The behaviour is the same when no hooks are present or an empty set of hooks are present.
❯ node p2.js 1
then callback ran with eid 1 tid 0
Attaching an empty init hook magically makes the context appear:
❯ node p2.js 2
then callback ran with eid 7 tid 6
Replacing the promise example with a setTimeout
or fs.readFile
has the things working correctly in all scenarios.
// the rest of the code is the same
setTimeout(() => {
console.log(`timeout callback ran with eid ${ah.executionAsyncId()} tid ${ah.triggerAsyncId()}`);
}, 1);
~/tmp/ah
❯ node p2.js 1
timeout callback ran with eid 6 tid 1
~/tmp/ah
❯ node p2.js 2
timeout callback ran with eid 6 tid 1