-
Notifications
You must be signed in to change notification settings - Fork 29.6k
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
premature doEmitWarning Unhandled promise rejection #18108
Comments
Here is another side of the bug. Here the debugger complains that the second rejection is not handled, but it was earlier, before the second call. This odd behaviour would be solved if the suggested fix is implemented (ie: warn and complain only when/if last reference being deleted). "use strict"; Promise.all([ |
I don't think this is really something that can be done. IIRC the only way to check ref counts would be PersistentBase::IsNearDeath but we don't have persistent handles of every promise created because that would be a pretty big overhead. |
An oft-cited workaround is this: "use strict";
let p = Promise.reject()
p.catch(() => {}); // <<
setTimeout(()=>{
p.catch(
()=>{console.log("caught")})
}, 1000) |
This is not a problem, this is a design choice, the alternative has false negatives and the false positives are better. This is why we have a |
Warnings for unhandled promise rejections should only be declared after the last reference to promise is removed and not during tick handling as is currently done.
The following example should not generate a warning. p rejection is handled.
"use strict";
let p = Promise.reject()
setTimeout(()=>{
p.catch(
()=>{console.log("caught")})
}, 1000)
Only after all references to p are gone, does node know the rejection was not handled.
Debugger listening on ws://127.0.0.1:43271/d7e878b8-45d9-4c4f-98e3-d760fb7b8074
(node:9480) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): undefined
warning.js:18
(node:9480) [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.
warning.js:18
(node:9480) PromiseRejectionHandledWarning: Promise rejection was handled asynchronously (rejection id: 1)
here is a more realistic example
"use strict";
function promise_to_do_something(i){
if(i == 0){
return Promise.reject("i don't like 0's")
} else {
return new Promise((resolve, reject)=>{
// emulate doing something
setTimeout(()=>{
if (Math.random()<0.5){
reject()
} else {
resolve()
}
}, 1000)})
}
}
promise_to_do_something(0)
.then(()=>{ console.log("they all passed")})
.catch(()=>{console.log("handle rejection")})
the above generates a warning while debugging, but there is no reason for this.
a cludge around this node bug, is to always delay before calling Promise.reject
"use strict";
function promise_to_do_something(i){
if(i == 0){
// I want to reject now, but node prematurely complains, so delay my rejection
return new Promise ((resolve, reject)=>{
setTimeout(()=>{ reject("i don't like 0's")})
})
} else {
return new Promise((resolve, reject)=>{
// emulate doing something
setTimeout(()=>{
if (Math.random()<0.5){
reject()
} else {
resolve()
}
}, 1000)})
}
}
promise_to_do_something(0)
.then(()=>{ console.log("they all passed")})
.catch(()=>{console.log("handle rejection")})
if you think the above cludge is ok, then the following example is most realistic and the cludge does not work.
"use strict";
function promise_to_do_something(i){
if(i == 0){
// I want to reject now, but node prematurely complains, so delay my rejection
return new Promise ((resolve, reject)=>{
setTimeout(()=>{ reject("i don't like 0's")})
})
} else {
return new Promise((resolve, reject)=>{
// emulate doing something
setTimeout(()=>{
if (Math.random()<0.5){
reject()
} else {
resolve()
}
}, 1000)})
}
}
let p = []
for (let i=0; i<10; i++){
p.push(promise_to_do_something(i))
}
Promise.all(p)
.then(()=>{ console.log("they all passed")})
.catch(()=>{console.log("handle rejection")})
The cleanest solution is for node to complain about unhandled promise rejection if references to the promise are none existing (ie: when last reference is deleted). This is the only way node knows a promise rejection will not be handled. This is clean from a semantic point of view.
The text was updated successfully, but these errors were encountered: