Heim > Artikel > Web-Frontend > Erläuterung der JavaScript-Ausnahmebehandlung
Wenn die JavaScript-Engine den JavaScript-Code ausführt, können verschiedene Ausnahmen auftreten, z. B. Syntaxausnahmen, fehlende Funktionen in der Sprache und eine abnormale Ausgabe vom Server oder Benutzer, die dazu führt Anomalien.
Die Javascript-Engine ist Single-Threaded. Sobald also eine Ausnahme auftritt, stoppt die Javascript-Engine normalerweise die Ausführung, blockiert nachfolgenden Code und löst eine Ausnahmemeldung aus Bei vorhersehbaren Ausnahmen sollten wir sie abfangen und Benutzern oder Entwicklern korrekt anzeigen.
throw und Promise.reject() können Ausnahmen vom Typ Zeichenfolge auslösen und einen Fehler auslösen Ausnahme des Objekttyps.
Eine Ausnahme des Objekttyps Error enthält nicht nur Ausnahmeinformationen, sondern auch einen Traceback-Stack, sodass Sie die Anzahl der Codezeilen, in denen der Fehler auftritt, leicht ermitteln können Traceback-Stack.
Es wird daher empfohlen, eine Fehler-Objekttypausnahme anstelle einer Zeichenfolgentypausnahme auszulösen.
Erstellen Sie Ihren eigenen Ausnahmekonstruktor
function MyError(message) { var instance = new Error(message); instance.name = 'MyError'; Object.setPrototypeOf(instance, Object.getPrototypeOf(this)); return instance; } MyError.prototype = Object.create(Error.prototype, { constructor: { value: MyError, enumerable: false, writable: true, configurable: true } }); if (Object.setPrototypeOf) { Object.setPrototypeOf(MyError, Error); } else { MyError.__proto__ = Error; } export default MyError;
Werfen Sie benutzerdefinierte Ausnahmetypen in den Code und fangen Sie sie ab
try { throw new MyError("some message"); } catch(e){ console.log(e.name + ":" + e.message); }
throw expression;throw
-Anweisung wird verwendet, um eine benutzerdefinierte Ausnahme auszulösen. Die Ausführung der aktuellen Funktion wird gestoppt (Anweisungen nach throw werden nicht ausgeführt) und die Steuerung wird an den ersten catch-Block im Aufrufstapel übergeben. Wenn in der Aufruffunktion kein catch-Block vorhanden ist, wird das Programm beendet.
Try/Catchtry { console.log('before throw error'); throw new Error('throw error'); console.log('after throw error'); } catch (err) { console.log(err.message); } // before throw error // throw error
try { try_statements } [catch (exception) { catch_statements }] [finally { finally_statements }]Try/Catch
wird hauptsächlich zum Abfangen von Ausnahmen verwendet. Die try/catch-Anweisung enthält einen try-Block und mindestens einen catch-Block oder einen finally-Block. Es folgen drei Formen Die try-Anweisung:
Fügen Sie Anweisungen oder Funktionen ein, die Ausnahmen erzeugen können catch
-Block enthält die auszuführende Anweisung. Wenn eine Ausnahme imtry-Block ausgelöst wird, erfasst der catch-Block die Ausnahmeinformationen und führt catch-Block: Wenn im try-Block keine Ausnahme ausgelöst wird, wird dieser catch-Block übersprungen. Der Block finally wird nach dem Block
tryund dem Block catch ausgeführt. Es wird immer ausgeführt, unabhängig davon, ob eine Ausnahme ausgelöst oder abgefangen wird. Wenn Ausnahmeinformationen im Block finally ausgelöst werden, werden die Ausnahmeinformationen im Block try überschrieben. Wenn ein Wert vom finally
-Block zurückgegeben wird, wird dieser Wert zum Rückgabewert des gesamtentry { try { throw new Error('can not find it1'); } finally { throw new Error('can not find it2'); } } catch (err) { console.log(err.message); } // can not find it2try-catch-finally
, unabhängig davon ob es einen finally-Block gibt. Die 🎜>return-Anweisungen sind in try und catch. Dazu gehören Ausnahmen, die innerhalb von catch-Blöcken ausgelöst werden. Try/Catch-Leistung
function test() { try { throw new Error('can not find it1'); return 1; } catch (err) { throw new Error('can not find it2'); return 2; } finally { return 3; } } console.log(test()); // 3Ein bekanntes Anti-Optimierungsmuster ist die Verwendung von
Die in V8 verwendeten try/catch
-Anweisungen (die gleiche Situation kann in anderen JS-Engines auftreten) können vom V8-Compiler nicht optimiert werden. Weitere Informationen finden Sie unter http://www.html5rocks.com/en/tutorials/speed/v8/window.onerror
, indem Sie einen Ereignis-Listener fürwindow.onerror erfasst. Und erfassen Sie gleichzeitig einige Informationen über die Ausnahme.
window.onerror = function (message, source, lineno, colno, error) { }
message
source
lineno
colno
error
-Objekt mit einem Traceback-Stack try/catch, der keine Ausnahmen im asynchronen Code abfangen kann löst die Ausnahme global aus und
window.onerrorkann sie abfangen. In Chrome kann
window.onerrortry { setTimeout(() => { throw new Error("some message"); }, 0); } catch (err) { console.log(err); } // Uncaught Error: some messageAusnahmen in Skriptdateien erkennen, auf die von anderen Domänen verwiesen wird, und diese Ausnahmen als
window.onerror = (msg, url, line, col, err) => { console.log(err); } setTimeout(() => { throw new Error("some message"); }, 0); // Error: some messagemarkieren. Wenn Sie diese aus anderen Domänen importierten Skriptdateien nicht verarbeiten möchten, können Sie sie über das Tag
im Programm herausfiltern. In Firefox, Safari oder IE11 werden jedoch keine domänenübergreifenden JS-Ausnahmen eingeführt. Selbst in Chrome erkennt Chrome diese nicht mehr, wenn Sie try/catch verwenden domänenübergreifende Ausnahmen. Script error
在Chrome中,如果你想通过 window.onerror 来获取到完整的跨域异常信息,那么这些跨域资源必须提供合适的跨域头信息。
new Promise((resolve,reject)=>{ reject(); })
Promise.resolve().then((resolve,reject)=>{ reject(); });
Promise.reject();
throw expression;
promiseObj.then(undefined, (err)=>{ catch_statements });
promiseObj.catch((exception)=>{ catch_statements })
在 JavaScript 函数中,只有 return / yield / throw 会中断函数的执行,其他的都无法阻止其运行到结束的。
在 resolve / reject 之前加上 return 能阻止往下继续运行。
without return
:
Promise.resolve() .then(() => { console.log('before excute reject'); reject(new Error('throw error')); console.log('after excute reject'); }) .catch((err) => { console.log(err.message); }); // before excute reject // throw error // after excute reject
use return
:
Promise.resolve() .then(() => { console.log('before excute reject'); return reject(new Error('throw error')); console.log('after excute reject'); }) .catch((err) => { console.log(err.message); }); // before excute reject // throw error
无论是 try/catch 还是 promise 都能捕获到的是“同步”异常
reject 是回调,而 throw 只是一个同步的语句,如果在另一个异步的上下文中抛出,在当前上下文中是无法捕获到的。
因此在 Promise 中使用 reject 抛出异常。否则 catch 有可能会捕捉不到。
Promise.resolve() .then(() => { setTimeout(()=>{ throw new Error('throw error'); },0); }) .catch((err) => { console.log(err); }); // Uncaught Error: throw error
Promise.resolve() .then(() => { return new Promise((resolve, reject) => { setTimeout(() => { reject(new Error('throw error')); }, 0); }); }) .catch((err) => { console.log(err); }); // Error: throw error
window.onunhandledrejection
与 window.onerror
类似,在一个JavaScript Promise 被 reject 但是没有 catch 来捕捉这个 reject时触发。并且同时捕获到一些关于异常的信息。
window.onunhandledrejection = event => { console.log(event.reason); }
event
事件是 PromiseRejectionEvent 的实例,它有两个属性:
event.promise
:被 rejected 的 JavaScript Promise
event.reason
:一个值或 Object 表明为什么 promise 被 rejected,是 Promise.reject() 中的内容。
因为 Promise 可以延后调用 catch 方法,若在抛出 reject 时未调用 catch 进行捕捉,但稍后再次调用 catch,此时会触发 rejectionhandled 事件。
window.onrejectionhandled = event => { console.log('rejection handled'); } let p = Promise.reject(new Error('throw error')); setTimeout(()=>{ p.catch(e=>{console.log(e)}); },1000); // Uncaught (in promise) Error: throw error // 1秒后输出 // Error: throw error // rejection handled
代码中抛出的异常,一种是要展示给用户,一种是展示给开发者。
对于展示给用户的异常,一般使用 alert 或 toast 展示;对于展示给开发者的异常,一般输出到控制台。
在一个函数或一个代码块中可以把抛出的异常统一捕捉起来,按照不同的异常类型以不同的方式展示,对于。
需要点击确认的异常类型:
ensureError.js
function EnsureError(message = 'Default Message') { this.name = 'EnsureError'; this.message = message; this.stack = (new Error()).stack; } EnsureError.prototype = Object.create(Error.prototype); EnsureError.prototype.constructor = EnsureError; export default EnsureError;
弹窗提示的异常类型:
toastError.js
function ToastError(message = 'Default Message') { this.name = 'ToastError'; this.message = message; this.stack = (new Error()).stack; } ToastError.prototype = Object.create(Error.prototype); ToastError.prototype.constructor = ToastError; export default ToastError;
提示开发者的异常类型:
devError.js
function DevError(message = 'Default Message') { this.name = 'ToastError'; this.message = message; this.stack = (new Error()).stack; } DevError.prototype = Object.create(Error.prototype); DevError.prototype.constructor = DevError; export default DevError;
异常处理器:
抛出普通异常时,可以带上 stackoverflow 上问题的列表,方便开发者查找原因。
errorHandler.js
import EnsureError from './ensureError.js'; import ToastError from './toastError.js'; import DevError from './devError.js'; import EnsurePopup from './ensurePopup.js'; import ToastPopup from './toastPopup.js'; function errorHandler(err) { if (err instanceof EnsureError) { EnsurePopup(err.message); } else if (err instanceof ToastError) { ToastPopup(err.message); }else if( err instanceof DevError){ DevError(err.message); }else{ error.message += ` https://stackoverflow.com/questions?q=${encodeURI(error.message)}` console.error(err.message); } } window.onerror = (msg, url, line, col, err) => { errorHandler(err); } window.onunhandledrejection = event =>{ errorHandler(event.reason); }; export default errorHandler;
Das obige ist der detaillierte Inhalt vonErläuterung der JavaScript-Ausnahmebehandlung. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!