-
Notifications
You must be signed in to change notification settings - Fork 29.8k
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
promise: warn on unhandled rejections #6439
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,8 @@ | |
|
||
const promiseRejectEvent = process._promiseRejectEvent; | ||
const hasBeenNotifiedProperty = new WeakMap(); | ||
const promiseToGuidProperty = new WeakMap(); | ||
var lastPromiseId = 1; | ||
const pendingUnhandledRejections = []; | ||
|
||
exports.setup = setupPromises; | ||
|
@@ -18,16 +20,23 @@ function setupPromises(scheduleMicrotasks) { | |
|
||
function unhandledRejection(promise, reason) { | ||
hasBeenNotifiedProperty.set(promise, false); | ||
promiseToGuidProperty.set(promise, lastPromiseId++); | ||
addPendingUnhandledRejection(promise, reason); | ||
} | ||
|
||
function rejectionHandled(promise) { | ||
var hasBeenNotified = hasBeenNotifiedProperty.get(promise); | ||
if (hasBeenNotified !== undefined) { | ||
hasBeenNotifiedProperty.delete(promise); | ||
const uid = promiseToGuidProperty.get(promise); | ||
promiseToGuidProperty.delete(promise); | ||
if (hasBeenNotified === true) { | ||
process.nextTick(function() { | ||
process.emit('rejectionHandled', promise); | ||
if(!process.emit('rejectionHandled', promise)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
process.emitWarning('Possibly Unhandled Promise Rejection Handled ' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The message There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it's all confusing terminology, I'm very open to different naming - the PR is a strawman to discuss this sort of thing exactly. Maybe 'Previous reported promise rejection handled'? |
||
+ '(unhandled rejection id: ' + uid +') ', | ||
'PromiseRejectionHandledWarning'); | ||
} | ||
}); | ||
} | ||
|
||
|
@@ -41,9 +50,12 @@ function setupPromises(scheduleMicrotasks) { | |
var reason = pendingUnhandledRejections.shift(); | ||
if (hasBeenNotifiedProperty.get(promise) === false) { | ||
hasBeenNotifiedProperty.set(promise, true); | ||
const uid = promiseToGuidProperty.get(promise); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
if (!process.emit('unhandledRejection', reason, promise)) { | ||
// Nobody is listening. | ||
// TODO(petkaantonov) Take some default action, see #830 | ||
process.emitWarning('Possibly unhandled promise rejection ' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we should double emit. Why not just print it, or use the internal warning logic directly? I also definitely don't think this should be "catchable" in the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Well, the point of this PR was to use @jasnell's idea of treating them as warnings. If we consider them warning and not errors initially I see double benefit: A) It's theoretically sound, since we're not claiming it's an error but a warning (like adding a lot of listeners to an EventEmitter). Note that rejections are pretty rare (like actual exceptions) and unhandled rejections even more so - so the performance penalty here is negligible. By emitting a warning rather than directly printing an error - I think we're leaving a much bigger opportunity for a long term solution: people realize warnings might go away, can be turned off, can be reported to another channel than errors and so on. This does not contradict a "throw on unhandled GC" or another "long term" solution. It does solve the problem of promises being terribly hard for users to debug with the current default which is what people always complain about in StackOverflow and forums. I think it's a reasonable compromise and that we haven't been fair to our users since we landed There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could potentially check the listener count for unhandledRejection first and only emit if it's greater than zero, otherwise emit the warning. This is precisely the kind of thing emitWarning is for. -1 for printing directly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm happy with I'd quibble that we should probably log this as an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @jasnell what you are describing is exactly the behavior in this PR, emitWarning is only called if there are no There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @chrisdickinson's point makes sense. |
||
+ '(unhandled rejection id: ' + uid +'): ' | ||
+ reason, | ||
'UnhandledPromiseRejectionWarning'); | ||
} else { | ||
hadListeners = true; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe
let
?