Come gestire Uncaught (in promise) DOMException in JavaScript
Quando vedete qualcosa come,
dove è specificato "(in promise)", indica semplicemente che un oggetto Promise è stato rifiutato, e non è stato catturato.
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 si tratta di programmazione asincrona, questo significa fondamentalmente che si è verificato un errore asincrono, e dall'avvento delle funzioni asincrone, quando una Promessa viene rifiutata e non catturata, viene registrato l'errore, come si vede nell'immagine sopra.
Il modo più semplice per catturare un errore di Promessa è quello di utilizzare il metodo Promise catch. 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'
Qui, potete vedere che stiamo usando try {} catch() {}, ma poiché è dentro una funzione asincrona, opera in modo asincrono, e quindi cattura gli errori asincroni.
(FTR, assicuratevi di fare qualcosa con i vostri errori, sincroni o asincroni - a differenza del codice di esempio sopra. Ovviamente registrare solo 'Caught!' non è utile :)