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

資訊專欄INFORMATION COLUMN

Node 錯(cuò)誤處理之挖坑系列

afishhhhh / 1938人閱讀

摘要:一中的對象包含了錯(cuò)誤的具體信息,包括錯(cuò)誤堆棧等。不源碼了,特別簡單,自己去一下。

一. Error

????JS 中的 Error 對象. 包含了錯(cuò)誤的具體信息,包括 name、message、錯(cuò)誤堆棧 stack 等。可以以 new Error 方式創(chuàng)建實(shí)例拋出,或調(diào)用 Error.captureStackTrace 為已有對象添加 stack 錯(cuò)誤堆棧信息 而后拋出

二. 錯(cuò)誤拋出幾種方式

Throw
Javascript 拋出的異常,是以 throw 方法拋出,未必都是 Error 的實(shí)例,但通過 nodeJs 或者 js 運(yùn)行時(shí)發(fā)生的錯(cuò)誤,都是 Error 的實(shí)例

EventEmitter
Nodejs 形式的錯(cuò)誤回調(diào),大部分流 & 異步事件都衍生自 EventEmitter 類 || 實(shí)例,如 fs, process, stream 等

Process
程序運(yùn)行過程中拋出的異常,或由底層庫拋出,或是運(yùn)行中發(fā)生的一些 SyntaxError 之類

三. 錯(cuò)誤捕獲幾種方式

try .. catch

常用的一種捕獲錯(cuò)誤方式,瀏覽器 || node 環(huán)境均適用

缺點(diǎn):只針對同步異常有效

    try {
        throw new Error("Something went wrong here")
    } catch (err) {
        console.log(err)
    }

EventEmitter

????由 Events 模塊提供的 EventEmitter 類,基于 Observer 模式做的 publish/subscribe,通過 .on("error", ...) || .addEventlistener("error", ...) 注冊 subscriber,.emit() 發(fā)布事件,但會(huì)有最大的 maxListener 的限制,可更改。
????不 show 源碼了,特別簡單,自己去 look 一下。如 koa 的 app 就是基于 EventEmitter 的擴(kuò)展,因此可以通過監(jiān)聽 error

    class Koa extends EventEmitter {...}
    
    let app = new Koa()
    app.emit("error", ..)
    app.on("error", ...)

Process

Process 進(jìn)程對象也是 EventEmitter 的實(shí)例,可通過如下兩事件監(jiān)聽 error

unhandledRejection
????promise 的回調(diào)報(bào)錯(cuò),可通過監(jiān)聽該事件 catch,但要注意由于 promise 的 rejection catched 不知道會(huì)在啥時(shí)候才發(fā)生,所以實(shí)際上可能在 unhandledRejection 事件觸發(fā)后才 catch 了這個(gè)信息,對應(yīng)有 rejectionHandled 事件監(jiān)聽,如下:

    process.on("rejectionHandled", p => {
        console.log("It has been handled")
    })
    
    process.on("unhandledRejection", (reason, p) => {
        console.log("Went here")
    })
    
    let test = new Promise((resolve, reject) => {
        let err = new Error("Just for a test")
        err.name = "TestError"
        reject(err)
    })
    
    setTimeout(() => {
        test.catch(err => {
            console.log("Excample work!")
            console.log(err)
        })
    }, 10000)

    // 打印出來的信息順序是:
    // Went here
    // It has been handled
    // Excample work!
    // { TestError: Just for a test
    // ....(stack message here) }

(承上)
uncaughtException
????其余 js 運(yùn)行中發(fā)生 || 拋出的未捕獲錯(cuò)誤,均可通過監(jiān)聽該事件解決,若不進(jìn)行該事件的監(jiān)聽,發(fā)生異常時(shí),會(huì)直接導(dǎo)致程序 crash
????但不建議用這種方式 catch,程序運(yùn)行中的錯(cuò)誤 更應(yīng)該是拋出來,所有的 error 都 catch 的話,豈不是程序都可以看成無 bug 了
????but 在打錯(cuò)誤日志的時(shí)候是需要 catch 上報(bào)日志的,但是在上報(bào)完后,需要繼續(xù)把 error throw,對于 uncaughtException callback 中拋出的異常不會(huì)再捕獲,而是以非 0 的狀態(tài)碼 exit

    // Promise Rejection
    process.on("unhandledRejection", err => {
        process.nextTick(() => { throw err }))
    })
    // 終極 boss
    process.on("uncaughtException", err => {...})
};
四.小結(jié)

以上以一張圖為總結(jié):

五. 源碼解讀

補(bǔ)充之前沒補(bǔ)充完的內(nèi)容,下圖為 node 中對于 process 的初始化等系列流程

node.cc 其實(shí)是 node 運(yùn)行主要的文件,其中定義了三個(gè)重載函數(shù) Start,調(diào)用順序?yàn)?3 → 2 → 1,每個(gè)函數(shù)參數(shù)不同處理不同的邏輯;

isolate->AddMessageListener 的監(jiān)聽事件 OnMessage 會(huì)在 js 運(yùn)行發(fā)生錯(cuò)誤時(shí)觸發(fā),嗯,是的,只有 error 才會(huì)傳遞 ;這很好的解釋了為什么 process 監(jiān)聽 uncaughtException 就可以監(jiān)聽到所有的拋出的非 promise 異常;

OnMessage 調(diào)用了 FatalException 函數(shù),F(xiàn)atalException 引用 process._fatalException 并傳入 error (env 是 env.h 中聲明的 Environment 類實(shí)例,fatal_exception_string 也是其中定義的,返回值為 "_fatalException");
以下為 FatalException 函數(shù)的部分內(nèi)容

void FatalException(Isolate* isolate,
                    Local error,
                    Local message) {
...(省略)
  Local fatal_exception_string = env->fatal_exception_string(); // "_fatalException"
  Local fatal_exception_function =
      process_object->Get(fatal_exception_string).As();
...(省略)
if (exit_code == 0) {
    TryCatch fatal_try_catch(isolate); // 調(diào)用 v8::TryCatch 
    
    // Do not call FatalException when _fatalException handler throws
    fatal_try_catch.SetVerbose(false); // 關(guān)鍵點(diǎn)

    // this will return true if the JS layer handled it, false otherwise
    Local caught =
        fatal_exception_function->Call(process_object, 1, &error); // 運(yùn)行 process._fatalException 函數(shù)

    if (fatal_try_catch.HasCaught()) { // 捕獲錯(cuò)誤
      // the fatal exception function threw, so we must exit
      ReportException(env, fatal_try_catch);
      exit_code = 7;
    }

    if (exit_code == 0 && false == caught->BooleanValue()) {
      ReportException(env, error, message);
      exit_code = 1;
    }
  }
...(省略)
}

在調(diào)用 _fatalException 函數(shù)前,先調(diào)用 v8::TryCatch::setVerbose 把 verbose 設(shè)置為 false,則運(yùn)行時(shí)拋出的異常就不會(huì)再觸發(fā) FatalException ;在捕獲到運(yùn)行錯(cuò)誤后,把 exit_code 設(shè)為 7,并返回;這就解釋了 為什么在 uncaughtException 時(shí)拋出的異常不會(huì)再重新觸發(fā)回調(diào),要知道 EventEmitter 可沒幫你做這樣的事情

_fatalException 在觸發(fā) "uncaughtException" 事件前其實(shí)是會(huì)優(yōu)先檢查 domain 是否存在,當(dāng) domain 不存在時(shí)才會(huì)調(diào)用 uncaughtException 的,但 domain 這個(gè) api 已經(jīng)被廢除了,也就不累述了

unhandledRejection 事件的觸發(fā)整體思路也差不多,首先會(huì)調(diào)用 SetupPromises 初始化,然后調(diào)用 v8::Isolate::SetPromiseRejectCallback 進(jìn)行監(jiān)聽 ... 并且跟 uncaughtException 不同的是 unhandledRejection 的觸發(fā)只會(huì)打印 warning 并不會(huì)把整個(gè)程序給 crash 了

六. END

若本文有誤,歡迎隨時(shí)指正

參考鏈接
V8 API Reference Guide

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

轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/91927.html

相關(guān)文章

  • 關(guān)于前端接口測試的探索和挖坑

    摘要:本文主要關(guān)注的是接口測試。所謂接口測試,就是檢查系統(tǒng)提供的接口是否符合事先撰寫的接口文檔。作為接口測試的解決方案,我們必須具備通用性與易用性。 開始 最近幾年,前端測試漸漸被人重視,相關(guān)的框架和方法已經(jīng)比較成熟。斷言庫有should, expect, chai。 單元測試框架有mocha, jasmine, Qunit。 模擬瀏覽器測試環(huán)境有Phantomjs, Slimerjs。 集...

    Crazy_Coder 評論0 收藏0
  • 關(guān)于前端接口測試的探索和挖坑

    摘要:本文主要關(guān)注的是接口測試。所謂接口測試,就是檢查系統(tǒng)提供的接口是否符合事先撰寫的接口文檔。作為接口測試的解決方案,我們必須具備通用性與易用性。 開始 最近幾年,前端測試漸漸被人重視,相關(guān)的框架和方法已經(jīng)比較成熟。斷言庫有should, expect, chai。 單元測試框架有mocha, jasmine, Qunit。 模擬瀏覽器測試環(huán)境有Phantomjs, Slimerjs。 集...

    zxhaaa 評論0 收藏0
  • node學(xué)習(xí)系列基礎(chǔ)(二)

    摘要:由于這種特性,某一個(gè)任務(wù)的后續(xù)操作,往往采用回調(diào)函數(shù)的形式進(jìn)行定義。另外,回調(diào)函數(shù)本身的第一個(gè)參數(shù),約定為上一步傳入的錯(cuò)誤對象。這種寫法有一個(gè)很大的好處,就是說只要判斷回調(diào)函數(shù)的第一個(gè)參數(shù),就知道有沒有出錯(cuò),如果不是,就肯定出錯(cuò)了。 REPL環(huán)境 在命令行鍵入node命令,后面沒有文件名,就進(jìn)入一個(gè)Node.js的REPL環(huán)境(Read–eval–print loop,讀取-求值-輸出...

    zhaot 評論0 收藏0
  • 迪米特法則

    摘要:個(gè)人博客原文迪米特法則設(shè)計(jì)模式六大原則之五迪米特法則。老師便給同學(xué)們講解了這個(gè)例子,讓學(xué)生感受一番迪米特法則。總結(jié)迪米特法則主要講述的觀點(diǎn)是高內(nèi)聚低耦合。 個(gè)人博客原文:迪米特法則 showImg(https://segmentfault.com/img/remote/1460000017779272?w=960&h=520); 設(shè)計(jì)模式六大原則之五:迪米特法則。 簡介 姓名:迪米特法...

    OnlyMyRailgun 評論0 收藏0
  • 深入了解JavaScript 中的For循環(huán)詳解

    摘要:將品牌的標(biāo)價(jià)全部加蘇南的專欄交流公眾號(hào)不會(huì)對空數(shù)組進(jìn)行檢測。方法用于調(diào)用數(shù)組的每個(gè)元素,并將元素傳遞給回調(diào)函數(shù)。 showImg(https://segmentfault.com/img/bVblSSO?w=1008&h=298); 前言: ? 今天我想分享一個(gè)有關(guān)于循環(huán)篩選的知識(shí)點(diǎn),也許是前端小白的你首先想到的是用for循環(huán)做篩選,但我這種小菜鳥想到的就是map(工作中很喜歡...

    linkin 評論0 收藏0

發(fā)表評論

0條評論

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