摘要:主要用于捕捉異常。這包括在塊里拋出的異常。并且同時捕獲到一些關于異常的信息。秒后輸出統一異常處理代碼中拋出的異常,一種是要展示給用戶,一種是展示給開發者。
當 JavaScript 引擎執行 JavaScript 代碼時,有可能會發生各種異常,例如是語法異常,語言中缺少的功能,由于來自服務器或用戶的異常輸出而導致的異常。
而 Javascript 引擎是單線程的,因此一旦遇到異常,Javascript 引擎通常會停止執行,阻塞后續代碼并拋出一個異常信息,因此對于可預見的異常,我們應該捕捉并正確展示給用戶或開發者。
Error對象throw 和 Promise.reject() 可以拋出字符串類型的異常,而且可以拋出一個 Error 對象類型的異常。
一個 Error 對象類型的異常不僅包含一個異常信息,同時也包含一個追溯棧這樣你就可以很容易通過追溯棧找到代碼出錯的行數了。
所以推薦拋出 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
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 errorTry / Catch
try { try_statements } [catch (exception) { catch_statements }] [finally { finally_statements }]
try/catch 主要用于捕捉異常。try/catch 語句包含了一個 try 塊, 和至少有一個 catch 塊或者一個 finally 塊,下面是三種形式的 try 聲明:
try...catch
try...finally
try...catch...finally
try 塊中放入可能會產生異常的語句或函數
catch 塊中包含要執行的語句,當 try 塊中拋出異常時,catch 塊會捕捉到這個異常信息,并執行 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-catch-finally 的返回值,無論是否有 return 語句在 try 和 catch 中。這包括在 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()); // 3Try / Catch 性能
有一個大家眾所周知的反優化模式就是使用 try/catch。
在V8(其他JS引擎也可能出現相同情況)函數中使用了 try/catch 語句不能夠被V8編譯器優化。參考http://www.html5rocks.com/en/tutorials/speed/v8/
window.onerror通過在 window.onerror 上定義一個事件監聽函數,程序中其他代碼產生的未被捕獲的異常往往就會被 window.onerror 上面注冊的監聽函數捕獲到。并且同時捕獲到一些關于異常的信息。
window.onerror = function (message, source, lineno, colno, error) { }
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標記將其過濾掉。然而,在Firefox、Safari或者IE11中,并不會引入跨域的JS異常,即使在Chrome中,如果使用 try/catch 將這些討厭的代碼包圍,那么Chrome也不會再檢測到這些跨域異常。
在Chrome中,如果你想通過 window.onerror 來獲取到完整的跨域異常信息,那么這些跨域資源必須提供合適的跨域頭信息。
Promise中的異常 Promise中拋出異常new Promise((resolve,reject)=>{ reject(); })
Promise.resolve().then((resolve,reject)=>{ reject(); });
Promise.reject();
throw expression;Promise中捕捉異常
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 errorThrow or Reject
無論是 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 errorwindow.onunhandledrejection
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() 中的內容。
window.rejectionhandled因為 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;
歡迎關注:Leechikit
原文鏈接:segmentfault.com到此本文結束,歡迎提問和指正。
寫原創文章不易,若本文對你有幫助,請點贊、推薦和關注作者支持。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/88927.html
摘要:但如果忽視異常輕則影響功能運行,重則導致系統崩潰,造成經濟損失。異常處理捕獲異常捕獲關鍵字與一致,都是使用。語句塊表示無論是否發生異常,語句塊代碼一定會被執行。 不少前端工程師看到這個標題可能會產生質問: 我js用得好好的,能后端能APP,為什么還要學習Python? 至少有下面兩個理由: 學習曲線。ES6之后的JavaScript(TypeScript)的在語法上和Python有很...
摘要:單元測試會體現出以上錯誤處理程序的作用如果出現問題,錯誤處理程序就會返回。同時錯誤會展開堆棧,這對調試非常有幫助。展開堆棧處理異常的一種方式是在調用堆棧的頂部加入。確保你的錯誤處理處在相同域中,這樣會保留原始消息,堆棧和自定義錯誤對象。 JavaScript的事件驅動范式增添了豐富的語言,也是讓使用JavaScript編程變得更加多樣化。如果將瀏覽器設想為JavaScript的事件驅動...
摘要:幸運的是,使用符號創建的構造器,如果在不使用來調用,則始終會報錯,即使在非嚴格模式下也不會產生問題。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項目原文:Bugs and Errors 譯者:飛龍 協議:CC BY-NC-SA 4.0 自豪地采用谷歌翻譯 部分參考了《JavaScript 編程精解(第 2 版)》 調試的難度是開始編寫代碼的兩倍。 因此,如...
摘要:我們使用單元測試來驗證一下我們使用了配合做單元測試。我們編寫相應的單元測試你會發現,如果出現異常,只是簡單的返回。但是在上面異常拋出的時候,解釋器已經不在中了,因此無法被捕獲。 譯者按: 錯誤是無法避免的,妥善處理它才是最重要的! 原文: A Guide to Proper Error Handling in JavaScript Related Topics: 譯者: Funde...
摘要:會自動調用轉換函數將這個表達式的結果轉換為一個布爾值。語句語句與語句的關系最為密切,而且也是在其他語言中普遍使用的一種流控制語句。 表達式在 JavaScript 中是短語,那么語句就是整句命令。表達式用來計算出一個值,語句用來執行以使某件事發生。從本質上看,語句定義了 JavaScript 中的主要語法,語句通常使用一或多個關鍵字來完成給定任務。語句可以很簡單,例如通知函數退出;也可...
閱讀 2472·2021-10-12 10:11
閱讀 1219·2021-10-11 10:58
閱讀 3258·2019-08-30 15:54
閱讀 696·2019-08-30 13:59
閱讀 667·2019-08-29 13:07
閱讀 1392·2019-08-26 11:55
閱讀 2133·2019-08-26 10:44
閱讀 2620·2019-08-23 18:25