成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JavaScript的異常處理

PrototypeZ / 362人閱讀

摘要:主要用于捕捉異常。這包括在塊里拋出的異常。并且同時(shí)捕獲到一些關(guān)于異常的信息。秒后輸出統(tǒng)一異常處理代碼中拋出的異常,一種是要展示給用戶,一種是展示給開發(fā)者。

當(dāng) JavaScript 引擎執(zhí)行 JavaScript 代碼時(shí),有可能會(huì)發(fā)生各種異常,例如是語法異常,語言中缺少的功能,由于來自服務(wù)器或用戶的異常輸出而導(dǎo)致的異常。

Javascript 引擎是單線程的,因此一旦遇到異常,Javascript 引擎通常會(huì)停止執(zhí)行,阻塞后續(xù)代碼并拋出一個(gè)異常信息,因此對(duì)于可預(yù)見的異常,我們應(yīng)該捕捉并正確展示給用戶或開發(fā)者。

Error對(duì)象

throwPromise.reject() 可以拋出字符串類型的異常,而且可以拋出一個(gè) Error 對(duì)象類型的異常。

一個(gè) Error 對(duì)象類型的異常不僅包含一個(gè)異常信息,同時(shí)也包含一個(gè)追溯棧這樣你就可以很容易通過追溯棧找到代碼出錯(cuò)的行數(shù)了。

所以推薦拋出 Error 對(duì)象類型的異常,而不是字符串類型的異常。

創(chuàng)建自己的異常構(gòu)造函數(shù)

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 語句用來拋出一個(gè)用戶自定義的異常。當(dāng)前函數(shù)的執(zhí)行將被停止(throw 之后的語句將不會(huì)執(zhí)行),并且控制將被傳遞到調(diào)用堆棧中的第一個(gè) catch 塊。如果調(diào)用者函數(shù)中沒有 catch 塊,程序?qū)?huì)終止。

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 / Catch
try {
   try_statements
}
[catch (exception) {
   catch_statements
}]
[finally {
   finally_statements
}]

try/catch 主要用于捕捉異常。try/catch 語句包含了一個(gè) try 塊, 和至少有一個(gè) catch 塊或者一個(gè) finally 塊,下面是三種形式的 try 聲明:

try...catch

try...finally

try...catch...finally

try 塊中放入可能會(huì)產(chǎn)生異常的語句或函數(shù)

catch 塊中包含要執(zhí)行的語句,當(dāng) try 塊中拋出異常時(shí),catch 塊會(huì)捕捉到這個(gè)異常信息,并執(zhí)行 catch 塊中的代碼,如果在 try 塊中沒有異常拋出,這 catch 塊將會(huì)跳過。

finally 塊在 try 塊和 catch 塊之后執(zhí)行。無論是否有異常拋出或著是否被捕獲它總是執(zhí)行。當(dāng)在 finally 塊中拋出異常信息時(shí)會(huì)覆蓋掉 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 塊中返回一個(gè)值,那么這個(gè)值將會(huì)成為整個(gè) try-catch-finally 的返回值,無論是否有 return 語句在 trycatch 中。這包括在 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 性能

有一個(gè)大家眾所周知的反優(yōu)化模式就是使用 try/catch

在V8(其他JS引擎也可能出現(xiàn)相同情況)函數(shù)中使用了 try/catch 語句不能夠被V8編譯器優(yōu)化。參考http://www.html5rocks.com/en/tutorials/speed/v8/

window.onerror

通過在 window.onerror 上定義一個(gè)事件監(jiān)聽函數(shù),程序中其他代碼產(chǎn)生的未被捕獲的異常往往就會(huì)被 window.onerror 上面注冊(cè)的監(jiān)聽函數(shù)捕獲到。并且同時(shí)捕獲到一些關(guān)于異常的信息。

window.onerror = function (message, source, lineno, colno, error) { }

message:異常信息(字符串)

source:發(fā)生異常的腳本URL(字符串)

lineno:發(fā)生異常的行號(hào)(數(shù)字)

colno:發(fā)生異常的列號(hào)(數(shù)字)

error:Error對(duì)象(對(duì)象)

注意:Safari 和 IE10 還不支持在 window.onerror 的回調(diào)函數(shù)中使用第五個(gè)參數(shù),也就是一個(gè) Error 對(duì)象并帶有一個(gè)追溯棧

try/catch 不能夠捕獲異步代碼中的異常,但是其將會(huì)把異常拋向全局然后 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 能夠檢測(cè)到從別的域引用的script文件中的異常,并且將這些異常標(biāo)記為Script error。如果你不想處理這些從別的域引入的script文件,那么可以在程序中通過Script error標(biāo)記將其過濾掉。然而,在Firefox、Safari或者IE11中,并不會(huì)引入跨域的JS異常,即使在Chrome中,如果使用 try/catch 將這些討厭的代碼包圍,那么Chrome也不會(huì)再檢測(cè)到這些跨域異常。

在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 函數(shù)中,只有 return / yield / throw 會(huì)中斷函數(shù)的執(zhí)行,其他的都無法阻止其運(yùn)行到結(jié)束的。

resolve / reject 之前加上 return 能阻止往下繼續(xù)運(yùn)行。

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
Throw or Reject

無論是 try/catch 還是 promise 都能捕獲到的是“同步”異常

reject 是回調(diào),而 throw 只是一個(gè)同步的語句,如果在另一個(gè)異步的上下文中拋出,在當(dāng)前上下文中是無法捕獲到的。

因此在 Promise 中使用 reject 拋出異常。否則 catch 有可能會(huì)捕捉不到。

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.onunhandledrejectionwindow.onerror 類似,在一個(gè)JavaScript Promise 被 reject 但是沒有 catch 來捕捉這個(gè) reject時(shí)觸發(fā)。并且同時(shí)捕獲到一些關(guān)于異常的信息。

window.onunhandledrejection = event => { 
    console.log(event.reason);
}

event事件是 PromiseRejectionEvent 的實(shí)例,它有兩個(gè)屬性:

event.promise:被 rejected 的 JavaScript Promise

event.reason:一個(gè)值或 Object 表明為什么 promise 被 rejected,是 Promise.reject() 中的內(nèi)容。

window.rejectionhandled

因?yàn)?Promise 可以延后調(diào)用 catch 方法,若在拋出 reject 時(shí)未調(diào)用 catch 進(jìn)行捕捉,但稍后再次調(diào)用 catch,此時(shí)會(huì)觸發(fā) 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
統(tǒng)一異常處理

代碼中拋出的異常,一種是要展示給用戶,一種是展示給開發(fā)者。

對(duì)于展示給用戶的異常,一般使用 alerttoast 展示;對(duì)于展示給開發(fā)者的異常,一般輸出到控制臺(tái)。

在一個(gè)函數(shù)或一個(gè)代碼塊中可以把拋出的異常統(tǒng)一捕捉起來,按照不同的異常類型以不同的方式展示,對(duì)于。

需要點(diǎn)擊確認(rèn)的異常類型:
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;

提示開發(fā)者的異常類型:
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;

異常處理器:
拋出普通異常時(shí),可以帶上 stackoverflow 上問題的列表,方便開發(fā)者查找原因。
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;

歡迎關(guān)注:Leechikit
原文鏈接:segmentfault.com

到此本文結(jié)束,歡迎提問和指正。
寫原創(chuàng)文章不易,若本文對(duì)你有幫助,請(qǐng)點(diǎn)贊、推薦和關(guān)注作者支持。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/88927.html

相關(guān)文章

  • JavaScript到Python之異常

    摘要:但如果忽視異常輕則影響功能運(yùn)行,重則導(dǎo)致系統(tǒng)崩潰,造成經(jīng)濟(jì)損失。異常處理捕獲異常捕獲關(guān)鍵字與一致,都是使用。語句塊表示無論是否發(fā)生異常,語句塊代碼一定會(huì)被執(zhí)行。 不少前端工程師看到這個(gè)標(biāo)題可能會(huì)產(chǎn)生質(zhì)問: 我js用得好好的,能后端能APP,為什么還要學(xué)習(xí)Python? 至少有下面兩個(gè)理由: 學(xué)習(xí)曲線。ES6之后的JavaScript(TypeScript)的在語法上和Python有很...

    xcold 評(píng)論0 收藏0
  • JavaScript中錯(cuò)誤正確處理方式,你用對(duì)了嗎?

    摘要:單元測(cè)試會(huì)體現(xiàn)出以上錯(cuò)誤處理程序的作用如果出現(xiàn)問題,錯(cuò)誤處理程序就會(huì)返回。同時(shí)錯(cuò)誤會(huì)展開堆棧,這對(duì)調(diào)試非常有幫助。展開堆棧處理異常的一種方式是在調(diào)用堆棧的頂部加入。確保你的錯(cuò)誤處理處在相同域中,這樣會(huì)保留原始消息,堆棧和自定義錯(cuò)誤對(duì)象。 JavaScript的事件驅(qū)動(dòng)范式增添了豐富的語言,也是讓使用JavaScript編程變得更加多樣化。如果將瀏覽器設(shè)想為JavaScript的事件驅(qū)動(dòng)...

    chaos_G 評(píng)論0 收藏0
  • JavaScript 編程精解 中文第三版 八、Bug 和錯(cuò)誤

    摘要:幸運(yùn)的是,使用符號(hào)創(chuàng)建的構(gòu)造器,如果在不使用來調(diào)用,則始終會(huì)報(bào)錯(cuò),即使在非嚴(yán)格模式下也不會(huì)產(chǎn)生問題。 來源:ApacheCN『JavaScript 編程精解 中文第三版』翻譯項(xiàng)目原文:Bugs and Errors 譯者:飛龍 協(xié)議:CC BY-NC-SA 4.0 自豪地采用谷歌翻譯 部分參考了《JavaScript 編程精解(第 2 版)》 調(diào)試的難度是開始編寫代碼的兩倍。 因此,如...

    wujl596 評(píng)論0 收藏0
  • 處理JavaScript異常正確姿勢(shì)

    摘要:我們使用單元測(cè)試來驗(yàn)證一下我們使用了配合做單元測(cè)試。我們編寫相應(yīng)的單元測(cè)試你會(huì)發(fā)現(xiàn),如果出現(xiàn)異常,只是簡單的返回。但是在上面異常拋出的時(shí)候,解釋器已經(jīng)不在中了,因此無法被捕獲。 譯者按: 錯(cuò)誤是無法避免的,妥善處理它才是最重要的! 原文: A Guide to Proper Error Handling in JavaScript Related Topics: 譯者: Funde...

    lushan 評(píng)論0 收藏0
  • JavaScript 闖關(guān)記》之語句

    摘要:會(huì)自動(dòng)調(diào)用轉(zhuǎn)換函數(shù)將這個(gè)表達(dá)式的結(jié)果轉(zhuǎn)換為一個(gè)布爾值。語句語句與語句的關(guān)系最為密切,而且也是在其他語言中普遍使用的一種流控制語句。 表達(dá)式在 JavaScript 中是短語,那么語句就是整句命令。表達(dá)式用來計(jì)算出一個(gè)值,語句用來執(zhí)行以使某件事發(fā)生。從本質(zhì)上看,語句定義了 JavaScript 中的主要語法,語句通常使用一或多個(gè)關(guān)鍵字來完成給定任務(wù)。語句可以很簡單,例如通知函數(shù)退出;也可...

    OBKoro1 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

PrototypeZ

|高級(jí)講師

TA的文章

閱讀更多
最新活動(dòng)
閱讀需要支付1元查看
<