Como lidar com Uncaught (in promise) DOMException in JavaScript
Quando você vê algo como,
where "(in promise)" é especificado, ele indica simplesmente que um objeto Promessa foi rejeitado, e não foi pego.
In brief, something like the below could generate a Promise error:
- var x = "hello";
- new Promise((resolve,reject) => {
- if(typeof x !== "number")
- return reject(new TypeError("x must be numeric"));
- // ...
- });
Here, because ‘x’ is a string and not a number, ‘reject’ is called. Quando se trata de programação assíncrona, isto significa basicamente que ocorreu um erro assíncrono, e desde o advento das funções assíncronas, quando uma promessa é rejeitada e não capturada, ela registra o erro, como visto na imagem acima.
A maneira mais simples de capturar um erro da promessa é usar o método de captura da promessa. Rewriting the code above as follows would allow you to catch the error:
- var x = "hello";
- new Promise((resolve,reject) => {
- if(typeof x !== "number")
- return reject(new TypeError("x must be numeric"));
- // ...
- }).catch((err)=>{
- console.log('Caught!');
- });
Now, instead of logging a thrown error, Caught! is logged.
Now, to get into a little more depth on error management in async programming. When an error is thrown in normal, linear programming and is not caught, the error will be logged:
- function square(x) {
- if(typeof x !== "number")
- throw new TypeError("Argument 'x' must be numeric");
- return x * x;
- }
- square("hello");
- // "Uncaught Error: Argument 'x' must be a number"
This you’re probably pretty familiar with.
The same thing, however, will also happen for errors thrown in asynchronous functions. For instance:
- async function callServer(message) {
- if(typeof message !== "string")
- throw new TypeError("Argument 'message' must be a string");
- return JSON.parse(
- await fetch('/api/' + message)
- );
- }
- callServer(); // argument[0] === undefined, not a string!
- // "Uncaught (in promise) TypeError: Argument 'message' must be a string"
And you’ll notice, this cannot be caught with a regular try {} catch() {}, e.g., by trying to run the following right in the console:
- try {
- callServer();
- } catch(e) {}
- // still logs:
- // "Uncaught (in promise) TypeError: Argument 'message' must be a string"
This is because callServer() runs asynchronously and returns a Promise, but the try {} catch() {} here only catches synchronous errors. To catch this kind of error, you need to catch it as a Promise error. In asynchronous programming, there are two ways to do this:
1. Use the Promise ‘catch’ method, like from above. Since callServer() returns a Promise, we can simply do:
- callServer().catch(()=>{
- console.log('Caught!');
- });
2. Catch it in an async function. Unlike regular functions which cannot ‘catch’ Promise errors, async functions can catch both synchronous and asynchronous Promise errors:
- async function callServerCatchingErrors(...args) {
- try {
- await callServer(...args);
- } catch(e) {
- console.log('Caught!');
- }
- }
- callServerCatchingErrors();
- // passing undefined still raises an error internally,
- // but the error now doesn't escape 'callServerCatchingErrors'
Haqui, você pode ver que estamos usando try {} catch() {}, mas como está dentro de uma função assíncrona, ele opera de forma assíncrona, e assim captura os erros assíncronos.
(FTR, certifique-se de fazer algo com seus erros, síncrono ou assíncrono - ao contrário do código de exemplo acima. Obviamente, apenas registar 'Caught!' não é útil :)