Error Handling with Promises
JavaScript Error Handling with Promises (使用Promises处理JavaScript错误)
JavaScript promises allow asynchronous code to use structured error handling. The promise chains are served as a great way of error handling. (JavaScript承诺允许异步代码使用结构化错误处理。Promise链是一种很好的错误处理方式。)
Whenever a promise rejects, the control jumps to the nearest rejection handler.
One of the most useful methods of error-handling is .catch.
(每当promise拒绝时,控件都会跳转到最近的rejection处理程序。
错误处理最有用的方法之一是.catch。)
catch
catch (v.捕 ,捕获,捕拿,逮住 ,擒拿,捉拿)
As it was already mentioned, .catch is one of the most useful methods for error handling in JavaScript. (如前所述, .catch是JavaScript中最有用的错误处理方法之一。)
Let’s view a case, in which the URL to fetch is wrong (no such site), and the .catch method handles it:
fetch('https://noSuchServer.someText') // rejects
.then(response => response.json())
(.then (response = > response.json ()))
.catch(err => console.log(err)) // TypeError: failed to fetch (the text may vary)
But note that .catch is not immediate. It might appear after one or several .then. (但请注意, .catch不是即时的。它可能出现在一个或多个.then之后。)
Everything might be correct with the site, but the response is not valid JSON. The simplest way of catching all the errors is to append .catch to the end of the chain. Here is an example:
fetch('/promiseChaining/user.json')
.then(response => response.json())
(.then (response = > response.json ()))
.then(user => fetch(`https://api.github.com/users/${user.name}`))
.then(response => response.json())
(.then (response = > response.json ()))
.then(user => new Promise((resolve, reject) => {
let img = document.createElement('img');
img.src = user.avatarUrl;
img.className = "promiseAvatarExample";
document.body.append(img);
setTimeout(() => {
img.remove();
resolve(user);
}, 3000);
}))
.catch(error => console.log(error.message));
Usually, .catch doesn’t trigger. But, in case any of the promises, as mentioned earlier, rejects, it will catch it. (通常, .catch不会触发。但是,如果任何承诺,如前所述,拒绝,它会抓住它。)
Implicit try..catch
Implicit try..catch (隐式try.. catch)
There is an invisible try..catch around the code of a promise handler and promise executor. In case of an exception, it will be treated as a rejection. (有一个无形的尝试..在promise处理程序和promise执行程序的代码周围捕获。如果出现例外情况,将被视为拒绝。)
It is shown in the following code:
new Promise((resolve, reject) => {
throw new Error("Error!!");
}).catch(console.log); // Error: Error!!
It operates the same as this code:
new Promise((resolve, reject) => {
reject(new Error("Error!!"));
}).catch(console.log); // Error: Error!!
The invisible try..catch will catch the error and transform it into a rejected promise. It can happen both in the executor function and its handlers. In case you throw inside a .then handler, it means a rejected promise, and the control jumps to the closest error handler. (不可见的try.. catch将捕获错误并将其转换为已拒绝的promise。它可以在executor函数及其处理程序中发生。如果在.then处理程序内抛出,则表示已拒绝promise ,控件跳转到最接近的错误处理程序。)
An example will look like this:
new Promise((resolve, reject) => {
resolve("Yes");
}).then((result) => {
throw new Error("Error!!"); // rejects the promise
}).catch(console.log); // Error: Error!!
That may happen to all the errors, not just ones caused by the throw statement. (这可能发生在所有错误上,而不仅仅是由throw语句引起的错误。)
We can consider a programming error as an example:
new Promise((resolve, reject) => {
resolve("Yes");
}).then((result) => {
someFunction(); // no such function
}).catch(console.log); // ReferenceError: someFunction is not defined
The final .catch will catch both explicit rejections and accidental errors in the handlers. (最终的.catch将捕获处理程序中的显式拒绝和意外错误。)
Rethrowing
Rethrowing (正在重新抛掷)
As it was already stated, .catch at the end of the promise chain is equivalent to try..catch. You may have as many .then handlers as you like, then use a single .catch at the end of the chain for handling all the errors. (如前所述, promise链末尾的.catch等同于try.. catch。您可以拥有任意数量的.then处理程序,然后在链的末尾使用单个.catch来处理所有错误。)
The regulartry..catch allows you to analyze an error and rethrow it if it can’t be handled. A similar situation is possible for promises. (Regulartry.. catch允许您分析错误并在无法处理时重新抛出它。对于承诺,也可能出现类似的情况。)
If you throw inside .catch, then the control will go to the next nearest error handler. If you handle the error and finish normally, it will continue to the next nearest successful .then handler. (如果在.catch中抛出,则控件将转到下一个最近的错误处理程序。如果您处理错误并正常完成,它将继续到下一个最近的成功的.then处理程序。)
The example below illustrates the successful error-handling with .catch:
// the execution: catch -> then
new Promise((resolve, reject) => {
throw new Error("Error!!");
}).catch(function (error) {
console.log("The error-handling, continue normally");
}).then(() => console.log("The next successful handler runs"));
In the example above, the .catch block finishes normally. Hence, the next effective .then is called. (在上面的示例中, .catch块正常结束。因此,调用了下一个有效的.then。)
Now let’s check out another situation with .catch. The handler (*) catches the error but is not capable of handling it:
// the execution: catch -> catch -> then
new Promise((resolve, reject) => {
throw new Error("Error!!");
}).catch(function (error) { // (*)
if (error instanceof URIError) {
// handle
(处理)
} else {
console.log("Can't handle such a error");
throw error; // throwing this or that error jumps to the next catch
}
}).then(function () {
/* doesn't run here */
}).catch(error => { // (**)
console.log(`The unknown error: ${error}`);
// do not return anything => execution goes the usual way
});
The execution jumps from the initial .catch (*) to the following one down the chain. (执行从最初的.catch ( * )跳到链中的下一个。)
Unhandled Rejections
Unhandled Rejections (未处理的拒绝)
In this section, we will examine the cases when errors are not handled. (在本节中,我们将研究未处理错误的情况。)
Let’s see that you have forgotten to append .catch to the end of the chain. (让我们看看您忘记在链的末尾附加.catch。)
Here is an example:
new Promise(function () {
noSuchFunc(); // Error here, no such function
})
.then(() => {
// successful promise handlers
(//成功的promise处理程序)
}); // no append .catch at the end
If there is an error, the promise will be rejected. The execution will jump to the nearest rejection handler. But there exists none, and the error will get “stuck”.There isn’t any code for handling it. (如果出现错误, Promise将被拒绝。执行将跳转到最近的拒绝处理程序。但是不存在,错误将被“卡住”。没有任何代码来处理它。)
So, what will happen if an error is not caught by try..catch? The script will collapse with a console message. Things like that occur with unhandled promise rejections. (那么,如果try.. catch没有捕捉到错误,会发生什么?脚本将折叠并显示控制台消息。这种情况发生在未处理的承诺拒绝中。)
The engine of JavaScript usually tracks this kind of rejections, generating a global error. (JavaScript引擎通常会跟踪此类拒绝,从而生成全局错误。)
For catching such errors in the browser, you can use the event unhandledRejection, as follows:
window.addEventListener('unhandledRejection', function (event) {
// the event object has two special properties
(//event对象有两个特殊属性)
console.log(event.promise); // [object Promise] - error
console.log(event.reason); // Error: Error!! - the unhandled error
});
new Promise(function () {
throw new Error("Error!!");
}); // no catch to handle the error
So, in case there is an error, and no .catch can be found, the unhandledRejection will trigger getting the event object with the information regarding the error. (因此,如果出现错误,并且找不到.catch , unhandledRejection将触发获取事件对象,其中包含有关错误的信息。)
As a rule, this kind of errors are unrecoverable. The most proper solution in such circumstances is to inform the user about it, reporting the incident to the server. (一般来说,这种错误是不可恢复的。在这种情况下,最合适的解决方案是告知用户,并将事件报告给服务器。)
Non-browser environments, such as Node.js, include other options for tracking unhandled errors. (非浏览器环境(如Node.js )包括用于跟踪未处理错误的其他选项。)
Summary
Summary (概要)
One of the most significant assets of using promises is the way they allow you to handle errors. (使用Promise最重要的资产之一是它允许您处理错误的方式。)
Errors in the promises can be handled with .catch: no matter it’s a reject() call or an error thrown in a handler. It would be best if you put .catch precisely in the places where you want to handle errors. The handler analyzes the errors rethrowing the ones that are unknown (for example, programming mistakes).
In any other case, you need to have unhandledRejection event handler ( for browsers and analogs of different environments). It will track unhandled errors informing the user about them. It will help you avoid the collapse of your app. (在任何其他情况下,都需要unhandledRejection事件处理程序(适用于不同环境的浏览器和类似物)。它将跟踪未处理的错误,告知用户这些错误。它将帮助您避免应用崩溃。)