Translators press: use.catch() to catch all exceptions
- 原文: Async Await Error Handling in JavaScript
- Translator: Fundebug
The copyright of this article belongs to the original author
Exception handling in async/await is confusing. While there are many ways to handle async exceptions, even experienced developers sometimes get it wrong.
Suppose you have an asynchronous function called run(). In this article, I describe three ways to handle run() exception cases: try/catch, Go language style, and function calls using catch()(that is, run().catch()). I’ll explain to you why it’s almost enough to just catch().
try/catch
The first time you use async/await, you might try to surround each async operation with a try/catch. If you await a reject Promise, JavaScript throws an error that can be caught.
run();
async function run() {
try {
await Promise.reject(new Error("Oops!"));
} catch (error) {
error.message; // "Oops!"}}Copy the code
Try /catch can catch non-asynchronous exceptions.
run();
async function run() {
const v = null;
try {
await Promise.resolve("foo");
v.thisWillThrow;
} catch (error) {
// "TypeError: Cannot read property 'thisWillThrow' of null"error.message; }}Copy the code
So, you can just wrap all your code logic around a try/catch, right? Not exactly. The following code throws an unhandled Promise rejection. Await to convert a rejected promise into a grabable error, but the return does not.
run();
async function run() {
try {
// Note that this is return, not await
return Promise.reject(new Error("Oops!"));
} catch (error) {
// The code will not be executed here}}Copy the code
It is also impossible to get around with a return await.
Another disadvantage is that once you use try/catch, it’s hard to use. “To make Promise chain combinations.
Use the Go syntax
Another common way to do this is to use then() to turn a Promise that would otherwise need to be caught and processed with a catch() into a regular Promise. You then use if(ERR) to handle exceptions as in Go.
run();
async function throwAnError() {
throw new Error("Oops!");
}
async function noError() {
return 42;
}
async function run() {
// The '. Then (() => NULL, err => err) 'to match normal/abnormal conditions. If normal, return 'null'; If an exception occurs, 'err' is returned
let err = await throwAnError().then((a)= > null, err => err);
if(err ! =null) {
err.message; // 'Oops'
}
err = await noError().then((a)= > null, err => err);
err; // null
}
Copy the code
If you really want to return error and correct values at the same time, you can completely pretend to be using Go.
run();
async function throwAnError() {
throw new Error("Oops!");
}
async function noError() {
return 42;
}
async function run() {
// The `.then(v => [null, v], err => [err, null])` pattern
// You can use array deconstruction to match err and return values
let [err, res] = await throwAnError().then(
v= > [null, v],
err => [err, null]);if(err ! =null) {
err.message; // 'Oops'
}
err = await noError().then(v= > [null, v], err => [err, null]);
err; // null
res; / / 42
}
Copy the code
Using Go style error handling does not get rid of situations that return cannot catch. It also makes the whole code more complicated if you forget if(err! = null), there is a problem.
In general, there are two major disadvantages:
- The code is extremely repetitive, everywhere
if (err ! = null)
, really tired, and easy to miss; run()
Non-asynchronous errors in functions cannot be handled either;
Overall, it’s not much better than try/catch.
Used during function callscatch()
Both try/catch and Go language style exception handling have their own usage scenarios, but the best way to handle all exceptions is to use catch() after the run() function, like this :run().catch(). In other words, use a catch() to handle all errors in the run function, rather than writing code to handle each case in the run.
run()
.catch(function handleError(err) {
err.message; // Oops!
})
// Handle all exceptions in handleError
// Exit if handleError fails.
.catch(err= > {
process.nextTick((a)= > {
throw err;
});
});
async function run() {
await Promise.reject(new Error("Oops!"));
}
Copy the code
Remember that async functions always return promises. As long as there is an exception in the function, Promise will reject. Also, if an async function returns a reject Promise, the Promise will continue to be rejected.
run()
.catch(function handleError(err) {
err.message; // Oops!
})
.catch(err= > {
process.nextTick((a)= > {
throw err;
});
});
async function run() {
// Note: return is used instead of await
return Promise.reject(new Error("Oops!"));
}
Copy the code
Why use run().catch() instead of wrapping the entire run() function around a try/catch? Let’s first consider the case: if the catch part of a try/catch has an exception, what should we do? There is only one way to do this: use try/catch inside a catch. So the run().catch() mode makes exception handling very neat.
conclusion
It is better to have a global errorHandler to handle unexpected exceptions, such as run().catch(handleError), than to add try/catch to all possible errors in run().
About Fundebug
Fundebug focuses on real-time BUG monitoring for JavaScript, wechat applets, wechat games, Alipay applets, React Native, Node.js and Java online applications. Since its official launch on November 11, 2016, Fundebug has handled over 1 billion error events in total, and paid customers include Sunshine Insurance, Walnut Programming, Lychee FM, Zhangmen 1-to-1, Weimai, Qingtuanshe and many other brand enterprises. Welcome to try it for free!
Copyright statement
Reprint please indicate the author Fundebug and this article addresses: blog.fundebug.com/2019/07/24/…