deno: unhandledrejection is not working for anonymous async function promises. Some code works in nodejs

Deno (1.18.3)

import {delay} from "std/async/delay.ts";

globalThis.addEventListener("unhandledrejection", (error) => {
    console.error('unhandledRejection', error);
    e.preventDefault();
});

(async () => {
    throw 'failed';
})();


await delay(5_000);
console.log('success');

Node (19.1.0)

process.on('unhandledRejection', (error) => {
    console.error('unhandledRejection', error);
});

(async () => {
    throw 'failed';
})();

await new Promise((resolve) => setTimeout(resolve, 5_000));
console.log('success');

Result: error: Uncaught “failed”

Expected: success

About this issue

  • Original URL
  • State: closed
  • Created 2 years ago
  • Comments: 17 (13 by maintainers)

Commits related to this issue

Most upvoted comments

@bartlomieju

ideally we want to do “Node-style” handling at the very end, to let all user code event listeners handle it first.

That might also work. Do you suggest special event registration API like .addLastEventListener(type: string)? Or maybe define a special event which will be triggered after unhandledrejection, like afterunhandledrejection (accessible only from the internals)?

I was suggesting a private API like: Deno[Deno.internal].node.unhandledRejectionHandler

How about adding a special API to get listener count of EventTarget?

const listenerCount = Symbol("listenerCount"); // only available to Deno internals
class EventTarget {
  ...
  /** Gets the count of listeners */
  [listenerCount](type: string)]: number {...}
}

And use it like:

if (process.listenerCount("uncaughtException") === 0 && globalThis[listenerCount]("unhandledrejection") === 0) {
  throw event.reason;
}

After some debugging and discussion with @dsherret I pinpointed that this is caused by npm: imports, which suggests that it’s related to Node compatibility layer. I will debug it further, as it’s possibly related to https://github.com/denoland/deno/issues/16628