Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect UnhandledPromiseRejectionWarning for asynchronous called async function #23838

Closed
3 tasks done
ivanggq opened this issue May 29, 2020 · 1 comment · Fixed by #24131
Closed
3 tasks done

Incorrect UnhandledPromiseRejectionWarning for asynchronous called async function #23838

ivanggq opened this issue May 29, 2020 · 1 comment · Fixed by #24131

Comments

@ivanggq
Copy link

ivanggq commented May 29, 2020

Preflight Checklist

  • I have read the Contributing Guidelines for this project.
  • I agree to follow the Code of Conduct that this project adheres to.
  • I have searched the issue tracker for an issue that matches the one I want to file, without success.

Issue Details

  • Electron Version:
    • v9.0.0
  • Operating System:
    • Windows 10 (1909)
  • Last Known Working Electron version:
    • Not sure

Expected Behavior

UnhandledPromiseRejectionWarning warnings should not be printed since all promise rejections are handled.
Similar script executed in plain Node.js project (not Electron) with recent Node version (v12.16.1) does not produce these warnings.

Actual Behavior

UnhandledPromiseRejectionWarning warnings are printed even though all promise rejections are handled.

To Reproduce

git clone https://github.com/ivanggq/electron-async-vs-promise-issue.git -b master
cd electron-async-vs-promise-issue/
npm install
npm start

Screenshots

Additional Information

The focus of this bug is that the UnhandledPromiseRejectionWarning is printed only under the following conditions:

  • only for function f3(),
  • only when executed under Electron (it is not printed under plain Node project), and,
  • only when the function is called asynchronously (from a setTimeout() callback)

If any of the above conditions is changed, the warning is not printed. It is not printed

  • for functions f1() and f2(), or,
  • when executed from plain Node.js project (Electron-specific parts should be removed from the script), or,
  • when the functions are called directly from the main script (not from setTimeout() callback)

I am looking to get answer/discussion to the following questions:

  • Why the UnhandledPromiseRejectionWarning warning is printed when executed from Electron but not when executed in a plain Node.js project?
  • Technical explanation of under-the-hood difference between f1/f2 and f3? Is an additional promise created/destroyed leading to some internal detection logic to complain? Why is the warning printed twice?
  • Why this happens only when executed from an asynchronous callback?
  • Is there any incorrect behavior in Electron or Node.js that should be fixed? If the outcome is correct, this means the code I submit is wrong. Can you point me to documentation or technical specification explaining why f3 is wrong or discouraged, if so?
const { app } = require('electron');

const f1 = async () => {
    throw 'oops';
}

const f2 = () => {
    return new Promise((_, reject) => {
        reject('oops');
    });
}

const f3 = async () => {
    return new Promise((_, reject) => {
        reject('oops');
    });
}

setTimeout(() => {
    f1().catch((error) => {
        console.log('1 caught', error);
    });
}, 1000);

setTimeout(() => {
    f2().catch((error) => {
        console.log('2 caught', error);
    });
}, 2000);

setTimeout(() => {
    f3().catch((error) => {
        console.log('3 caught', error);
    });
}, 3000);

setTimeout(() => app.exit(), 4000);

Output:

1 caught oops
2 caught oops
(node:21316) UnhandledPromiseRejectionWarning: oops
(node:21316) UnhandledPromiseRejectionWarning: oops
(node:21316) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)
(node:21316) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 3)
(node:21316) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
(node:21316) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
3 caught oops
(node:21316) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 3)
(node:21316) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 3)
@codebytere
Copy link
Member

codebytere commented Jun 5, 2020

@ivanggq the duplication issue is a bug fixed by #22342 in latest 9.

What I can tell you at a glance:

PromiseRejectionHandledWarning: Promise rejection was handled asynchronously

means that the catch is happening on a subsequent tick, one farther than it should. The async keyword itself means that the function will wrap in a Promise - so there are two promises in play in f3. Node.js' behavior is correct - this is probably a subtle timers error in Electron.

This is also specific to the main process - it does not happen when Electron is run in Node.js emulation mode or when the same functions are put into the renderer process.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants