欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

node.js?express和koa中間件機制和錯誤處理機制

 更新時間:2022年07月05日 15:47:25   作者:??baymax??  
這篇文章主要介紹了node.js?express和koa中間件機制和錯誤處理機制,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的朋友可以參考一下

一、前言

大家可能都知道koa是express核心原班人馬寫的,那么他們?yōu)槭裁匆趀xpress后再造一個koa的輪子呢? 今天就給大家?guī)硪恍┓治?。希望能夠起到一個拋磚引玉的作用。

其實,這個題目也可以這么問, express有什么缺點? koa解決了一些express的什么問題? 這也在一些面試題中會這么問。所以,為了實現(xiàn)自己的理想(money), 志同道合的同志們可以隨我分析一下了。

我想先從express的一個非常重要的特征開始說起,那就是 中間件。 中間件貫穿了express的始終,我們在express中比較常用到應(yīng)用級的中間件,比如:

    const app = require('express')();
    app.use((req, res, next) => {
        // 做一些事情。。。
        next();
    })

再比如我們更常用到的路由級中間件。 我為什么要叫它是路由級的呢? 因為它的內(nèi)部也同樣維護著一個next

    app.get('/', (req, res, next) => {
        res.send('something content');
    })

這里中間件我不詳細展開。 后面有我對中間件的詳細解析,歡迎大家圍觀。

那么我們可以看到,其中會有個關(guān)鍵的next, 它在express內(nèi)部做的是從棧中獲取下一個中間件的關(guān)鍵。

那么重點來了, 我們開始研究express這里的實現(xiàn)會隱藏什么問題。

二、中間件問題解析

通過一個例子來看:

    const Express = require('express');
    const app = new Express();
    const sleep = () => new Promise(resolve => setTimeout(function(){resolve(1)}, 2000));
    const port = 8210;
    function f1(req, res, next) {
      console.log('this is function f1....');
      next();
      console.log('f1 fn executed done');
    }
    
    function f2(req, res, next) {
      console.log('this is function f2....');
      next();
      console.log('f2 fn executed done');
    }
    
    async function f3(req, res) {
      console.log('f3 send to client');
      res.send('Send To Client Done');
    }
    app.use(f1);
    app.use(f2);
    app.use(f3);
    app.get('/', f3)
    app.listen(port, () => console.log(`Example app listening on port ${port}!`))

理想下的返回,和真正的返回,目前是沒有問題的。

    this is function f1....
    this is function f2....
    f3 send to client
    f1 fn executed done
    f2 fn executed done

好的,那么再繼續(xù)下一個例子。 在下一個例子中,其它都是沒有變化的,只有一個地方:

    const sleep = () => new Promise(resolve => setTimeout(function(){resolve()}, 1000))
    async function f3(req, res) {
        await sleep();
      console.log('f3 send to client');
      res.send('Send To Client Done');
    }

這時你認為的返回值順序是什么樣的呢?

可能會認為跟上面的沒有變化,因為我們增加await了,照道理應(yīng)該等待await執(zhí)行完了,再去執(zhí)行下面的代碼。 其實結(jié)果并不是。

返回的結(jié)果是:

    this is function f1....
    this is function f2....
    f1 fn executed done
    f2 fn executed done
    f3 send to client

發(fā)生了什么?? 大家可能有點吃驚。但是,如果深入到express的源碼中去一探究竟,問題原因也就顯而易見了。

具體源碼我在這一篇中就不詳細分析了,直接說出結(jié)論:

因為express中的中間件調(diào)用不是Promise 所以就算我們加了async await 也不管用。

那么koa中是怎么使用的呢?

const Koa = require('koa');
const app = new Koa();
const sleep = () => new Promise(resolve => setTimeout(function(){resolve()}, 1000))
app.use(async (ctx, next) => {
    console.log('middleware 1 start');
    await next();
    console.log('middleware 1 end');
});
app.use(async (ctx, next) => {
    await sleep();
    console.log('middleware 2 start');
    await next();
    console.log('middleware 2 end');
});
app.use(async (ctx, next) => {
    console.log('middleware 3 start')
    ctx.body = 'test middleware executed';
})

不出所料, 實現(xiàn)的順序是:

middleware 1 start
middleware 2 start
middleware 3 start
middleware 2 end
middleware 1 end

原因是: koa 內(nèi)部使用了Promise,所以能夠控制順序的執(zhí)行。

綜合上面的例子,我們知道了express中中間件使用的時候,如果不清楚原理,是容易踩坑的。 而koa通過使用async 和 await next() 實現(xiàn)洋蔥模型,即:通過next,到下一個中間件,只要下面的中間件執(zhí)行完成后,才一層層的再執(zhí)行上面的中間件,直到全部完成。

三、錯誤邏輯捕獲

3.1 express的錯誤捕獲邏輯

同樣,先看express在錯誤邏輯的捕獲上有什么特點:

app.use((req, res, next) => {
    // c 沒有定義
    const a = c;
});
// 錯誤處理中間件
app.use((err, req, res, next) => {
    if(error) {
        console.log(err.message);
    }
    next()
})
process.on("uncaughtException", (err) => {
    console.log("uncaughtException message is::", err);
})

再看一個異步的處理:

app.use((req, res, next) => {
    // c 沒有定義
    try {
        setTimeout(() => {
            const a = c;
            next()
        }, 0)
    } catch(e) {
        console.log('異步錯誤,能catch到么??')
    }
});
app.use((err, req, res, next) => {
    if(error) {
        console.log('這里會執(zhí)行么??', err.message);
    }
    next()
})
process.on("uncaughtException", (err) => {
    console.log("uncaughtException message is::", err);
})

可以先猜一下同步和異步的會不會有所區(qū)別?

答案是: 有很大的區(qū)別?。?/code>

具體分開來看:

  • 同步的時候, 不會觸發(fā) uncaughtException, 而進入了錯誤處理的中間件。
  • 異步的時候,不會觸發(fā)錯誤處理中間件, 而會觸發(fā) uncaughtException

這中間發(fā)生了什么?

3.2 同步邏輯錯誤獲取的底層邏輯

邏輯是: express內(nèi)部對同步發(fā)生的錯誤進行了攔截,所以,不會傳到負責(zé)兜底的node事件 uncaughtException ,如果發(fā)生了錯誤,則直接繞過其它中間件,進入錯誤處理中間件。 那么,這里會有一個很容易被忽略的點, 那就是,即使沒有錯誤處理中間件做兜底,也不會進入node的 uncaughtException, 這時, 會直接報 500錯誤。

3.3 異步邏輯錯誤獲取的底層邏輯

還是因為express的實現(xiàn)并沒有把Promise考慮進去, 它的中間件執(zhí)行是同步順序執(zhí)行的。 所以如果有異步的,那么錯誤處理中間件實際是兜不住的,所以,express對這種中間件中的異步處理錯誤無能為力。

從上面的異步觸發(fā)例子來看, 除了錯誤處理中間件沒有觸發(fā),我們當中的try catch也沒有觸發(fā)。這是一個大家可能都會踩到的坑。 這里其實是與javascript的運行機制相關(guān)了。具體原因見本篇 JavaScript異步隊列進行try catch時的問題解決

所以要想去catch 當前的錯誤,那么就需要用 async await

app.use(async (req, res, next) => {
    try {
        await (() => new Promise((resolve, reject) => {
            http.get('http://www.example.com/testapi/123', res => {
                reject('假設(shè)錯誤了');
            }).on('error', (e) => {
                throw new Error(e);
            })
        }))();
    } catch(e) {
        console.log('異步錯誤,能catch到么??')
    }
});

這樣,我們的catch不僅可以獲取到, uncaughtException也可以獲取到。

3.4 koa的錯誤獲取邏輯

總體上是跟express差不多,因為js的底層處理還是一致的。但還是使用上有所差異。

上面也提過洋蔥模型,特點是最開始的中間件,在最后才執(zhí)行完畢,所以,在koa上,可以把錯誤處理中間件放到中間件邏輯最前面。

const http = require('http');
const Koa = require('koa');
const app = new Koa();
app.use(async (ctx, next)=>{
    try {
        await next();
    } catch (error) {
        // 響應(yīng)用戶
        ctx.status = 500;
        ctx.body = '進入默認錯誤中間件';
        // ctx.app.emit('error', error); // 觸發(fā)應(yīng)用層級錯誤事件
    }
});
app.use(async (ctx, next) => {
    await (() => new Promise((resolve, reject) => {
        http.get('http://www.example.com/testapi/123', res => {
            reject('假設(shè)錯誤了');
        }).on('error', (e) => {
            throw new Error(e);
        })
    }))();
    await next();
})

上面的代碼, reject出的錯誤信息,會被最上面的錯誤處理中間件捕獲。總結(jié)來說,js的底層機制是一樣的, 只是使用方法和細節(jié)點上不一樣,大家在用的時候注意一下,

到此這篇關(guān)于node.js express和koa中間件機制和錯誤處理機制的文章就介紹到這了,更多相關(guān)node.js express和koa內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 三種Node.js寫文件的方式

    三種Node.js寫文件的方式

    這篇文章主要為大家詳細介紹了三種Node.js寫文件的方式,感興趣的小伙伴們可以參考一下
    2016-03-03
  • npm使用國內(nèi)淘寶鏡像的兩種方法

    npm使用國內(nèi)淘寶鏡像的兩種方法

    npm install時候,默認是去npm鏡像源獲取,很多時候蝸牛一樣的速度,所以需要將安裝源設(shè)置成國內(nèi)的源,這樣速度就會快很多,本文就來介紹一下npm使用國內(nèi)淘寶鏡像的兩種方法,感興趣的可以了解一下
    2023-08-08
  • node.js?實現(xiàn)手機號驗證碼登錄功能

    node.js?實現(xiàn)手機號驗證碼登錄功能

    這篇文章主要介紹了node.js?實現(xiàn)手機號驗證碼登錄功能,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-08-08
  • 基于nodejs的雪碧圖制作工具的示例代碼

    基于nodejs的雪碧圖制作工具的示例代碼

    雪碧圖就是把很多小圖標合并為一張圖片,這篇文章主要介紹了基于nodejs的雪碧圖制作工具的示例代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Ubuntu 16.04 64位中搭建Node.js開發(fā)環(huán)境教程

    Ubuntu 16.04 64位中搭建Node.js開發(fā)環(huán)境教程

    如果想要在Ubuntu 16.04上安裝Node.js的話,這篇文章對你來說肯定很重要。Node.js從本質(zhì)上來說就是一個運行在服務(wù)端上的封裝好了輸入輸出流的javascript程序。本文給大家詳細介紹了在Ubuntu 16.04 64位搭建Node.js開發(fā)環(huán)境的步驟,有需要的朋友們可以參考學(xué)習(xí)。
    2016-10-10
  • nodejs使用http模塊發(fā)送get與post請求的方法示例

    nodejs使用http模塊發(fā)送get與post請求的方法示例

    這篇文章主要介紹了nodejs使用http模塊發(fā)送get與post請求的方法,結(jié)合實例形式分析了nodejs基于http模塊實現(xiàn)發(fā)送get與post請求具體操作技巧,需要的朋友可以參考下
    2018-01-01
  • NodeJS?基于?Dapr?構(gòu)建云原生微服務(wù)應(yīng)用快速入門教程

    NodeJS?基于?Dapr?構(gòu)建云原生微服務(wù)應(yīng)用快速入門教程

    Dapr?是一個可移植的、事件驅(qū)動的運行時,它使任何開發(fā)人員能夠輕松構(gòu)建出彈性的、無狀態(tài)和有狀態(tài)的應(yīng)用程序,并可運行在云平臺或邊緣計算中,它同時也支持多種編程語言和開發(fā)框架,本文重點介紹NodeJS云原生微服務(wù)應(yīng)用,感興趣的朋友一起看看吧
    2022-07-07
  • node.js利用mongoose獲取mongodb數(shù)據(jù)的格式化問題詳解

    node.js利用mongoose獲取mongodb數(shù)據(jù)的格式化問題詳解

    這篇文章主要給大家介紹了關(guān)于node.js利用mongoose獲取mongodb數(shù)據(jù)的格式化問題,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)把。
    2017-10-10
  • nodejs高大上的部署方式(PM2)

    nodejs高大上的部署方式(PM2)

    這篇文章主要介紹了nodejs高大上的部署方式(PM2) ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-09-09
  • 什么是Node.js?Node.js詳細介紹

    什么是Node.js?Node.js詳細介紹

    這篇文章主要介紹了什么是Node.js,Node.js能做什么,Node.js的優(yōu)缺點,Node.js的例子等,需要的朋友可以參考下
    2014-06-06

最新評論