JavaScript エンジンが JavaScript コードを実行すると、構文の例外、言語の機能の欠落、サーバーまたはユーザーからの異常な出力による例外など、さまざまな例外が発生する可能性があります。
そして、Javascriptエンジンはシングルスレッドであるため、例外が発生すると、Javascriptエンジンは通常実行を停止し、後続のコードをブロックし、例外メッセージをスローします。そのため、予見可能な例外については、それらをキャッチして正しく表示する必要がありますユーザーや開発者に。
Error objectthrow と Promise.reject() は、文字列型の例外をスローすることができ、また Error オブジェクト型の例外をスローすることができます。
AError オブジェクト型例外には例外情報が含まれるだけでなく、トレースバック スタックも含まれるため、トレースバック スタックを通じてエラーが発生したコードの行数を簡単に見つけることができます。
そのため、文字列型例外の代わりにError オブジェクト型例外をスローすることをお勧めします。
独自の例外コンストラクターを作成します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;
try { throw new MyError("some message"); } catch(e){ console.log(e.name + ":" + e.message); }
throw expression;
throw ステートメントをキャッチしてユーザー定義の例外をスローします。現在の関数の実行は停止され (throw の後のステートメントは実行されません)、制御は呼び出しスタック内の最初の catch ブロックに渡されます。呼び出し側関数に catch ブロックがない場合、プログラムは終了します。
try { 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は主に例外をキャッチするために使用されます。 try/catch ステートメントには、try ブロックと、少なくとも 1 つの catch ブロックまたは finally ブロックが含まれます。 try ステートメントの 3 つの形式は、次のとおりです。
try 例外を生成する可能性のあるステートメントまたは関数はブロック内に配置されます
catch ブロックには以下が含まれます実行されるステートメント。 try ブロックで例外がスローされた場合、catch ブロックは例外情報を取得し、try で例外がスローされなかった場合は catch ブロック内のコードを実行します。ブロック、この キャッチ ブロックはスキップされます。
finallyブロックは、tryブロックとcatchブロックの後に実行されます。例外がスローされたかキャッチされたかに関係なく、常に実行されます。 finallyブロックに例外情報がスローされた場合、tryブロック内の例外情報は上書きされます。
try { 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 it2
finallyブロックから返された場合、tryとにreturnステートメントがあるかどうかに関係なく、この値はtry-catch-finally全体の戻り値になります。キャッチ。これには、catch ブロック内でスローされた例外が含まれます。
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()); // 3
try/catch を使用するよく知られた最適化対策パターンがあります。
V8 で使用されるtry/catch ステートメント (同じ状況が他の JS エンジンでも発生する可能性があります) 関数は、V8 コンパイラーでは最適化できません。 http://www.html5rocks.com/en/tutorials/speed/v8/
window.onerrorを参照window.onerrorでイベントリスニング関数を定義することで、プログラム内の他のコードによって生成されたキャッチされないエラーが発生します。多くの場合、上記で登録された listen 関数 window.onerror によってキャッチされます。同時に、例外に関する情報を取得します。
window.onerror = function (message, source, lineno, colno, error) { }
message
: 例外情報 (文字列) message
:异常信息(字符串)
source
:发生异常的脚本URL(字符串)
lineno
:发生异常的行号(数字)
colno
:发生异常的列号(数字)
error
:Error对象(对象)
注意:Safari 和 IE10 还不支持在 window.onerror 的回调函数中使用第五个参数,也就是一个 Error 对象并带有一个追溯栈
try/catch 不能够捕获异步代码中的异常,但是其将会把异常抛向全局然后 window.onerror 可以将其捕获。
try { setTimeout(() => { throw new Error("some message"); }, 0); } catch (err) { console.log(err); } // Uncaught Error: some message
window.onerror = (msg, url, line, col, err) => { console.log(err); } setTimeout(() => { throw new Error("some message"); }, 0); // Error: some message
在Chrome中,window.onerror 能够检测到从别的域引用的script文件中的异常,并且将这些异常标记为Script error
。如果你不想处理这些从别的域引入的script文件,那么可以在程序中通过Script error
source
: 例外が発生したスクリプト URL (文字列)
lineno < /code>: 例外が発生した行番号(number)🎜🎜🎜🎜<code>colno
: 例外が発生した列番号(number)🎜🎜🎜🎜error
:エラー オブジェクト (オブジェクト)🎜🎜🎜🎜注: Safari と IE10 は、🎜window.onerror🎜 のコールバック関数の 5 番目のパラメーターの使用をまだサポートしていません。これは、トレースバック スタックを持つ 🎜Error🎜 オブジェクトです🎜🎜🎜try /catch🎜 非同期コード内の例外はキャッチできませんが、例外はグローバルにスローされ、🎜window.onerror🎜 はそれをキャッチできます。 🎜new Promise((resolve,reject)=>{ reject(); })
Promise.resolve().then((resolve,reject)=>{ reject(); });
スクリプト エラー
としてマークできます。他のドメインからインポートされたこれらのスクリプト ファイルを処理したくない場合は、プログラム内の Script error
タグを使用してそれらのスクリプト ファイルをフィルタリングして除外できます。ただし、Firefox、Safari、IE11 ではクロスドメイン JS 例外が導入されていません。これらの厄介なコードを 🎜try/catch🎜 で囲むと、Chrome はこれらの異常なクロスドメイン JS 例外を検出しなくなります。 🎜在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;
以上がJavaScriptの例外処理の説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。