Reputation: 4637
Javascript Promises if I had to oversimplify are to my understanding a "way to act upon stuff later, scheduled via the .then()
method".
After doing the following in my terminal:
BASE$> node
> var promise = Promise.reject("reason 42");
I was therefore supprised to see this result:
> (node:8783) UnhandledPromiseRejectionWarning: reason 42
(node:8783) 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: 1)
(node:8783) [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.
because I was about to write.
> promise.catch(console.log);
The thing that motiviates this question is:
Can I be reasonably sure that node.js
only pulls of this warnings (and threat "in the future I will bail completely", because of the code being run stepwise in the node.js console/REPL?
How has node.js
come already to the conclusion that the promise rejection was to be unhandled?
I have hence tested the following to work differently
var promise = Promise.reject("reason 42"); promise.catch(console.log);
tmp.js
) with content
var promise = Promise.reject("reason 42") promise.catch(console.log);`)via
node tmp.js
both yielding the expected output "reason 42
" not presenting any warning as shown above earlier.
Hence how does this work out? Can my assumption be confirmed that the determination of an unhandled promise in the node console REPL
, is reflection the reach end in each REPL
loop iteration?
Upvotes: 1
Views: 423
Reputation: 12637
I would like to extend on @estus answer, particularly the first sentence:
In order for promise rejection to be considered handled, it should be chained with catch or then with 2 arguments on same tick.
I'd not fully agree with that. I'd argument that every promise where then
or catch
has be called is fine, but when calling these methods you create new Promises and they have just inherited the problem.
We often talk about promise-chains, but actually it's a tree, as you can branch multiple "child-promises" from the very same "parent", and the error affects all of them.
const root = Promise.reject("reason 42");
const a = root.then(value => value*2)
.then(...);
const b = root.then(value => value*3)
.then(...);
So, you build a chain/tree of promises; an error occurs. The Error is propagated to the child-promises in that tree, ... If that (or any other) error reaches any leaf-promise (without being catched somewhere along the line) you'll get an UnhandledPromiseRejectionWarning
.
There are a million things you can do with promises and how you chain/branch them and how/where you catch your errors, ... so the best summary I can give you on that:
Since Promises
are all about time, you have time until the Error reaches the end of the chain to catch
it.
Can I be reasonably sure that node.js only pulls of this warnings (and threat "in the future I will bail completely", because of the code being run stepwise in the node.js console
Yes
Upvotes: 2
Reputation: 222474
In order for promise rejection to be considered handled, it should be chained with catch
or then
with 2 arguments on same tick.
This will cause UnhandledPromiseRejectionWarning
:
var promise = Promise.reject("reason 42");
setTimeout(() => {
promise.catch(console.error);
});
This won't cause UnhandledPromiseRejectionWarning
:
var promise = Promise.reject("reason 42");
promise.catch(console.error);
Asynchronously evaluated lines in Node.js REPL result in a delay between them. In order to evaluate lines synchronously in the order they were written, editor mode can be used. Or the code can be written to to be unambiguously evaluated as a block:
;{
var promise = Promise.reject("reason 42");
promise.catch(console.error);
}
Or IIFE:
(() => {
var promise = Promise.reject("reason 42");
promise.catch(console.error);
})()
Upvotes: 3