Skip to content

async_hooks: Awaited thenables have no async context after first tick #26064

Closed
@kjin

Description

@kjin
  • Version: 11.9, 10.15
  • Platform: macOS
  • Subsystem: async_hooks

If I do await { then: fn }, then code running in fn will always see an async ID of 1 until after an Immediate (or "lower priority" tick) is made, then it will start seeing 0 instead. I expect it instead to be the same async ID as the resource in which the call was made... see the below repro for expectations vs. actual results.

The culprit here is probably the same as in #22360, but discussion there has stalled. Also, I think the example here is easier to comprehend.

Repro

const asyncHooks = require('async_hooks');

// activate async_hooks
asyncHooks.createHook({
  init: () => {}
}).enable();

// a custom thenable
const thenable = () => ({
  then: (fn) => {
    console.log(asyncHooks.executionAsyncId());
    fn();
  }
});

async function main() {
  // On first tick
  console.log(asyncHooks.executionAsyncId()); // prints 1
  await thenable(); // prints 1 (expected)

  // After first thenable
  console.log(asyncHooks.executionAsyncId()); // prints incremented ID
  await thenable(); // still prints 1 (unexpected)

  // After high-priority tick
  await new Promise(res => process.nextTick(res)); // tick nextTick queue
  console.log(asyncHooks.executionAsyncId()); // prints incremented ID
  await thenable(); // still prints 1 (unexpected)

  // After Immediate
  await new Promise(res => setImmediate(res)); // tick immediate
  console.log(asyncHooks.executionAsyncId()); // prints incremented ID
  await thenable(); // prints 0 (unexpected)

  // A workaround
  console.log(asyncHooks.executionAsyncId()); // prints incremented ID
  await thenable().then(_ => _); // prints same as above (expected)
}

main().catch(console.error);

Real-world use case example

The knex module seems to sometimes make DB queries in a Promise.prototype.then wrapper. If the Promise implementation happens to be userland, like in bluebird, then async context will be unknown at the DB query call site.

Metadata

Metadata

Assignees

No one assigned

    Labels

    async_hooksIssues and PRs related to the async hooks subsystem.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions