Given the the following code:
var fs = require('fs');
var asyncErrorPromise = new Promise(function(resolve) {
fs.readFile('does/not/exist.blah', function(fileError, content) {
if (fileError) throw fileError;
resolve(content);
});
});
asyncErrorPromise
.then(function(content) {
console.log('content received: ' + content);
})
.catch(function(err) {
console.log('error received: ' + err.name);
});
I would expect that the fileError
that is thrown (because the file I try to load does not exist) will be caught by the Promise and funneled into the .catch()
statement. So in the end I'd have this output: error received: ENOENT
.
However, when I run this code I get the following instead:
if (err) throw err;
^
Error: ENOENT: no such file or directory, open 'does/not/exist.blah'
at Error (native)
So the error was not caught: it threw just as it normally would, as though it were outside a Promise.
Why is this happening?
Everything I can find to read about Promises is more concerned with errors being silently swallowed than with this problem, where it actually throws when you don't want it to!
And how should I achieve my intent here? Do I need to use try-catch statements and the reject
handler?
async and awaitInside an async function, you can use the await keyword before a call to a function that returns a promise. This makes the code wait at that point until the promise is settled, at which point the fulfilled value of the promise is treated as a return value, or the rejected value is thrown.
A promise is used to handle the asynchronous result of an operation. JavaScript is designed to not wait for an asynchronous block of code to completely execute before other synchronous parts of the code can run. With Promises, we can defer the execution of a code block until an async request is completed.
The Promise returned by catch() is rejected if onRejected throws an error or returns a Promise which is itself rejected; otherwise, it is fulfilled.
You cannot catch an error thrown in an asynchronous callback function using promises, since its context will be lost. In your case with Node, you will loose the context of the error in the process.on('uncaughtException')
handler, and the callback will run as its own event in the eventqueue, with its own context and scope.
Using promises, the correct solution will be to reject
the wrapping promise.
An alternative would be to use a Domain
object (Domain documentation), but it's pending deprecation. With a domain
you can maintain the context and register a handler for your errors, as below.
var domain = require('domain');
var d = domain.create();
d.on('error', function(err){
//Do something with your error
});
d.run(function(){
//Run your async code that might throw error
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With