溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

怎么在JavaScript中捕獲錯(cuò)誤

發(fā)布時(shí)間:2021-04-27 16:02:53 來(lái)源:億速云 閱讀:168 作者:Leah 欄目:開發(fā)技術(shù)

這篇文章將為大家詳細(xì)講解有關(guān)怎么在JavaScript中捕獲錯(cuò)誤,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

JavaScript的作用是什么

1、能夠嵌入動(dòng)態(tài)文本于HTML頁(yè)面。2、對(duì)瀏覽器事件做出響應(yīng)。3、讀寫HTML元素。4、在數(shù)據(jù)被提交到服務(wù)器之前驗(yàn)證數(shù)據(jù)。5、檢測(cè)訪客的瀏覽器信息。6、控制cookies,包括創(chuàng)建和修改等。7、基于Node.js技術(shù)進(jìn)行服務(wù)器端編程。

一、基本使用與邏輯

使用

try{
    //code....
}catch(err){
    //error handling
}finally{
    //no matter what happens in the try/catch (error or no error), this code in the finally statement should run. 
}

邏輯

怎么在JavaScript中捕獲錯(cuò)誤

二、特性

try...catch 僅適用于運(yùn)行時(shí)錯(cuò)誤,解釋階段錯(cuò)誤無(wú)法正常工作

try{
    {{{{{{{
}catch(err){
    console.error(err)
}
//引擎在‘parse-time'出錯(cuò),導(dǎo)致無(wú)法理解代碼,因此無(wú)法捕捉

try...catch 只能同步工作

try{
    setTimeout(function(){
        undefinedVariable;
    },1000)
}catch(err){
    console.error(err)
}
//setTimeout的回調(diào)函數(shù)執(zhí)行時(shí),引擎已經(jīng)離開try...catch結(jié)構(gòu)

finally 能讓try塊中的return語(yǔ)句失效

function test(){
  try {
    return 1;
  } catch(error) {
    return 2;
  } finally {
    return 3;
  }
}
console.log(test());
//3

三、錯(cuò)誤對(duì)象

當(dāng)程序發(fā)生error,js內(nèi)部會(huì)生成一個(gè)包含error細(xì)節(jié)的對(duì)象,該對(duì)象會(huì)被作為參數(shù)傳進(jìn)catch

對(duì)于所有內(nèi)置錯(cuò)誤,錯(cuò)誤對(duì)象具有兩個(gè)主要屬性

  • name 錯(cuò)誤類型

  • message 文本類型的錯(cuò)誤信息

  • stack (非標(biāo)準(zhǔn)屬性)發(fā)生錯(cuò)誤時(shí)的調(diào)用棧信息,主要用于調(diào)試

try {
  lalala; // error, variable is not defined!
} catch (err) {
  alert(err.name); // ReferenceError
  alert(err.message); // lalala is not defined
  alert(err.stack); // ReferenceError: lalala is not defined at (...call stack)

  // Can also show an error as a whole
  // The error is converted to string as "name: message"
  alert(err); // ReferenceError: lalala is not defined
}

理論上,我們可以throw任何東西作為錯(cuò)誤對(duì)象,但最好的習(xí)慣是throw一個(gè)具有name,message的對(duì)象,以便和內(nèi)置錯(cuò)誤對(duì)象保持兼容

番外:內(nèi)置的錯(cuò)誤對(duì)象

對(duì)象含義
ReferenceError引用未定義變量時(shí)觸發(fā)
SyntaxError使用不合法的語(yǔ)法結(jié)構(gòu)時(shí)觸發(fā)
TypeError值得類型非預(yù)期時(shí)觸發(fā)
URIError錯(cuò)誤使用全局URI函數(shù)如encodeURI()、decodeURI()等時(shí)觸發(fā)
RangeError對(duì)Array構(gòu)造函數(shù)使用錯(cuò)誤的長(zhǎng)度值,對(duì)Number.toExponential()、Number.toFixed()或Number.toPrecision()使用無(wú)效數(shù)字等
EvalError全局函數(shù)eval()中發(fā)生的錯(cuò)誤

四、較好的catch和throw策略

catch錯(cuò)誤不單單是為了防止程序掛掉,更重要的目的是方便調(diào)試,找bug,所以對(duì)錯(cuò)誤的處理策略,稍微可以體現(xiàn)出碼者的優(yōu)雅性

俗話說的好,碼者,人恒雅也,盡量遵循一個(gè)原則,catch只處理自己知道的錯(cuò)誤

舉個(gè)梨子

let json = '{ "age": 30 }'; 
try{
  let user = JSON.parse(json);  
  alert( user.name );
} catch (err) {
  console.error('JSON Error:'+err);
}

上述例子的catch策略能保證程序正常,因?yàn)閏atch塊能catch內(nèi)部所有的錯(cuò)誤,無(wú)論是JSON.parse出錯(cuò)還是user.name不存在報(bào)錯(cuò),都能被catch到,但兩種錯(cuò)誤都用同一種打印是不利于調(diào)試的,寫成下面這樣會(huì)好一點(diǎn)

let json = '{"age":30}'
try{
  let user =  JSON.parse(json);
  alert(user.name)
}catch(err){
   if(err instanceof SyntaxError){
       console.error('JSON Error:'+err);
   }
   else throw err;
}

每個(gè)catch塊處理自己知道得,可能會(huì)出現(xiàn)得錯(cuò)誤,就是說,編程人員在編程的時(shí)候,catch那些預(yù)料到的錯(cuò)誤,而將可能自己沒料到的錯(cuò)誤拋到外面。

五、Promise的錯(cuò)誤處理

眾所周知,Promise是會(huì)吞掉error的,因?yàn)閜romise的實(shí)現(xiàn)就在內(nèi)部對(duì)所有error進(jìn)行了捕獲,且捕獲到的error不是向外拋出(外指promise之外),而是沿著鏈找到最近的onreject回調(diào)傳入,所以promise的錯(cuò)誤處理只有兩種辦法

  1. 設(shè)置onreject回調(diào)

  2. 全局捕獲

舉個(gè)栗子

try{
    new Promise((resolve,reject)=>{
        throw new Error('promise error')
    }).catch(()=>{
        //錯(cuò)誤在最近的onreject回調(diào)被捕獲
        console.error(err);
    })
}catch(err){
    //永遠(yuǎn)不會(huì)執(zhí)行,promise吞掉error
    console.error(err);
}

另外需要注意,無(wú)論是執(zhí)行者函數(shù)(executor)和還是 promise 的處理程序(handler),內(nèi)部發(fā)生的錯(cuò)誤統(tǒng)統(tǒng)吞掉,相當(dāng)于被隱式catch,error會(huì)自動(dòng)找到最近的onreject回調(diào)傳進(jìn)去

try{
    new Promise((resolve,reject)=>{
        resolve();
    }).then(()=>{
        throw new Error('promise then error');
    }).catch((err){
        console.error(err);
    })
}catch(err){
    //地球毀滅之前都不會(huì)執(zhí)行
    console.error(err)
}

同理,在錯(cuò)誤找到onreject傳進(jìn)去之前,經(jīng)過的then注冊(cè)的onfulfilled回調(diào)統(tǒng)統(tǒng)失效,直到找到onreject回調(diào),處理之后,onreject回調(diào)之后的onfulfilled回調(diào)才正常

try {
    new Promise((resolve, reject) => {
        throw new Error('promise error')
    }).then((ret) => {
        //錯(cuò)誤沒有處理,失效
        console.log('then1:' + ret)
    }).catch((err) => {
        //錯(cuò)誤處理了,后序正常
        console.error(err);
        return 'handled'
    }).then((ret) => {
        //正常執(zhí)行
        console.log('then2' + ret);
    })
} catch (err) {
    //同樣的,人類毀滅之前都不會(huì)執(zhí)行
    console.error(err)
}

// Error:promise error
//then2handled

那整條鏈一個(gè)catch都沒設(shè)置會(huì)怎么樣呢?

那這個(gè)error就會(huì)擊穿地心,一直穿透到全局,根據(jù)宿主環(huán)境的不同觸發(fā)不同的全局事件,比如說瀏覽器中會(huì)觸發(fā) unhandledrejection事件,node環(huán)境中也會(huì)觸發(fā)unhandledRejection事件,一般會(huì)對(duì)這事件進(jìn)行監(jiān)聽,再顯示信息給編程人員或者用戶

番外1:chromium / v8 / v8 / 3.29.45 的 Promise內(nèi)部錯(cuò)誤捕捉

怎么在JavaScript中捕獲錯(cuò)誤

關(guān)于怎么在JavaScript中捕獲錯(cuò)誤就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI