国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

警示后人系列:為什么我沒有catch到回調函數中拋出的錯誤?

fnngj / 941人閱讀

摘要:回調函數的棧幀被放入時,執行棧是空的。總結用語句包裹回調函數的定義,無法捕獲到回調函數中的錯誤。如果回調函數運行時沒有外層函數,你必須在回調函數內部做錯誤的捕獲和處理。

今天犯了一個js中的錯誤,記錄一下警示后人:)

事情是這樣,koa會幫我們捕獲中間件中拋出的錯誤,從而不讓服務器崩潰,如下圖:

服務器為此次請求返回500,仍然能夠處理后續的請求。

從這一點出發,我就認為,我可以在中間件里面隨便throw,這樣koa就能在控制臺幫我打印出所有錯誤的信息,反正也不會對后續請求造成影響。

但是今天的錯誤是這樣的:

進程居然崩潰了!這樣上線豈不是要出事?

為什么koa這回沒有捕獲到我throw的錯誤呢?

用簡單的代碼模擬一下這個場景:

try {
  setTimeout(() => {
    try {
      throw 500;
    } catch (err) {
      console.log("err1", err);  // called
      throw err;
    }
  }, 0);
} catch (err) {
  console.log("err2", err)  // never called
}


可以看出,內層的try確實捕獲到了錯誤,但是當我們把這個錯誤繼續拋出,外層的try卻沒有捕獲到這個錯誤

原因在于,回調函數被異步調用時,外層try中的代碼其實已經執行完了,棧幀已經從執行棧中彈出。回調函數的棧幀被放入時,執行棧是空的

錯誤被拋出后,沿著執行棧,希望找到“外層”函數的try...catch語句。可是這個回調函數根本就沒有“外層”函數了,因此這是一個沒有被捕獲到的錯誤,這會造成進程的崩潰。

總結

用try語句包裹回調函數的定義,無法捕獲到回調函數中的錯誤。必須用try語句包裹運行時的外層函數。如果回調函數運行時沒有外層函數,你必須在回調函數內部做錯誤的捕獲和處理。

如果回調函數定義在Promise中,你可以直接在回調函數中調用reject(reason),讓這個Promise的訂閱者來處理錯誤:

const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    try {
      throw 500;
    } catch (err) {
      console.log("err1", err);  // called
      reject(err);
    }
  }, 0);
});

p.catch(err => {
  console.log("err3", err);  // called
});

如果回調函數由async function的await關鍵字來執行,那么可以通過reject Promise,讓async function中的try...catch捕獲到錯誤。

async function fun() {
  try {
    await new Promise((resolve, reject) => {
      setTimeout(() => {
        try {
          throw 500;
        } catch (err) {
          console.log("err1", err);  // called
          reject(err);
        }
      }, 0);
    });
  } catch (err) {
    console.log("err4", err);  // called
    throw err;
  }
}
try {
  fun();
} catch (err) {
  console.log("err5", err);  // not called
}

注意try {fun();}無法捕獲到錯誤,因為這個函數不是通過await來執行的。錯誤拋出的時候,這個try語句早已經執行完。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/93302.html

相關文章

  • Node 錯誤處理之挖坑系列

    摘要:一中的對象包含了錯誤的具體信息,包括錯誤堆棧等。不源碼了,特別簡單,自己去一下。 一. Error ????JS 中的 Error 對象. 包含了錯誤的具體信息,包括 name、message、錯誤堆棧 stack 等。可以以 new Error 方式創建實例拋出,或調用 Error.captureStackTrace 為已有對象添加 stack 錯誤堆棧信息 而后拋出showImg(...

    afishhhhh 評論0 收藏0
  • 解析 Promise 原理,實現一個Promise

    摘要:解析原理,實現一個概述這篇文章旨在解析的異步實現原理,并且以中的為藍本實現一個簡單的。具體的規范可以參見細節構造器中必須傳入函數,否則會拋出錯誤。中的回調返回值會影響返回的對象。執行器傳入構造器的為函數,并且在構造時就會執行。 解析 Promise 原理,實現一個Promise 概述 這篇文章旨在解析 Promise的異步實現原理,并且以 ES6中的 Promise 為藍本實現一個簡單...

    silenceboy 評論0 收藏0
  • JavaScript的異常處理

    摘要:主要用于捕捉異常。這包括在塊里拋出的異常。并且同時捕獲到一些關于異常的信息。秒后輸出統一異常處理代碼中拋出的異常,一種是要展示給用戶,一種是展示給開發者。 當 JavaScript 引擎執行 JavaScript 代碼時,有可能會發生各種異常,例如是語法異常,語言中缺少的功能,由于來自服務器或用戶的異常輸出而導致的異常。 而 Javascript 引擎是單線程的,因此一旦遇到異常,Ja...

    PrototypeZ 評論0 收藏0
  • 對JavaScript中的異步函數進行異常處理及測試

    摘要:總結最后總結一下從異步函數拋出的錯誤不會是普通的異常。異步函數和異步方法總是返回一個,無論是已解決還是被拒絕。要攔截異步函數中的異常,必須使用。 翻譯:瘋狂的技術宅原文:https://www.valentinog.com/bl... 本文首發微信公眾號:jingchengyideng歡迎關注,每天都給你推送新鮮的前端技術文章 可以在 Javascript 的異步函數中拋出錯誤嗎...

    bigdevil_s 評論0 收藏0
  • 對JavaScript中的異步函數進行異常處理及測試

    摘要:總結最后總結一下從異步函數拋出的錯誤不會是普通的異常。異步函數和異步方法總是返回一個,無論是已解決還是被拒絕。要攔截異步函數中的異常,必須使用。 翻譯:瘋狂的技術宅原文:https://www.valentinog.com/bl... 本文首發微信公眾號:jingchengyideng歡迎關注,每天都給你推送新鮮的前端技術文章 可以在 Javascript 的異步函數中拋出錯誤嗎...

    paulli3 評論0 收藏0

發表評論

0條評論

fnngj

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<