最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

node.js?express和koa中間件機(jī)制和錯(cuò)誤處理機(jī)制

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

一、前言

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

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

我想先從express的一個(gè)非常重要的特征開(kāi)始說(shuō)起,那就是 中間件。 中間件貫穿了express的始終,我們?cè)趀xpress中比較常用到應(yīng)用級(jí)的中間件,比如:

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

再比如我們更常用到的路由級(jí)中間件。 我為什么要叫它是路由級(jí)的呢? 因?yàn)樗膬?nèi)部也同樣維護(hù)著一個(gè)next

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

這里中間件我不詳細(xì)展開(kāi)。 后面有我對(duì)中間件的詳細(xì)解析,歡迎大家圍觀。

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

那么重點(diǎn)來(lái)了, 我們開(kāi)始研究express這里的實(shí)現(xiàn)會(huì)隱藏什么問(wèn)題。

二、中間件問(wèn)題解析

通過(guò)一個(gè)例子來(lái)看:

    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}!`))

理想下的返回,和真正的返回,目前是沒(méi)有問(wèn)題的。

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

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

    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');
    }

這時(shí)你認(rèn)為的返回值順序是什么樣的呢?

可能會(huì)認(rèn)為跟上面的沒(méi)有變化,因?yàn)槲覀冊(cè)黾觓wait了,照道理應(yīng)該等待await執(zhí)行完了,再去執(zhí)行下面的代碼。 其實(shí)結(jié)果并不是。

返回的結(jié)果是:

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

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

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

因?yàn)閑xpress中的中間件調(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';
})

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

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

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

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

三、錯(cuò)誤邏輯捕獲

3.1 express的錯(cuò)誤捕獲邏輯

同樣,先看express在錯(cuò)誤邏輯的捕獲上有什么特點(diǎn):

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

再看一個(gè)異步的處理:

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

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

答案是: 有很大的區(qū)別??!

具體分開(kāi)來(lái)看:

  • 同步的時(shí)候, 不會(huì)觸發(fā) uncaughtException, 而進(jìn)入了錯(cuò)誤處理的中間件。
  • 異步的時(shí)候,不會(huì)觸發(fā)錯(cuò)誤處理中間件, 而會(huì)觸發(fā) uncaughtException

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

3.2 同步邏輯錯(cuò)誤獲取的底層邏輯

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

3.3 異步邏輯錯(cuò)誤獲取的底層邏輯

還是因?yàn)閑xpress的實(shí)現(xiàn)并沒(méi)有把Promise考慮進(jìn)去, 它的中間件執(zhí)行是同步順序執(zhí)行的。 所以如果有異步的,那么錯(cuò)誤處理中間件實(shí)際是兜不住的,所以,express對(duì)這種中間件中的異步處理錯(cuò)誤無(wú)能為力。

從上面的異步觸發(fā)例子來(lái)看, 除了錯(cuò)誤處理中間件沒(méi)有觸發(fā),我們當(dāng)中的try catch也沒(méi)有觸發(fā)。這是一個(gè)大家可能都會(huì)踩到的坑。 這里其實(shí)是與javascript的運(yùn)行機(jī)制相關(guān)了。具體原因見(jiàn)本篇 JavaScript異步隊(duì)列進(jìn)行try catch時(shí)的問(wèn)題解決

所以要想去catch 當(dāng)前的錯(cuò)誤,那么就需要用 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è)錯(cuò)誤了');
            }).on('error', (e) => {
                throw new Error(e);
            })
        }))();
    } catch(e) {
        console.log('異步錯(cuò)誤,能catch到么??')
    }
});

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

3.4 koa的錯(cuò)誤獲取邏輯

總體上是跟express差不多,因?yàn)閖s的底層處理還是一致的。但還是使用上有所差異。

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

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 = '進(jìn)入默認(rèn)錯(cuò)誤中間件';
        // ctx.app.emit('error', error); // 觸發(fā)應(yīng)用層級(jí)錯(cuò)誤事件
    }
});
app.use(async (ctx, next) => {
    await (() => new Promise((resolve, reject) => {
        http.get('http://www.example.com/testapi/123', res => {
            reject('假設(shè)錯(cuò)誤了');
        }).on('error', (e) => {
            throw new Error(e);
        })
    }))();
    await next();
})

上面的代碼, reject出的錯(cuò)誤信息,會(huì)被最上面的錯(cuò)誤處理中間件捕獲??偨Y(jié)來(lái)說(shuō),js的底層機(jī)制是一樣的, 只是使用方法和細(xì)節(jié)點(diǎn)上不一樣,大家在用的時(shí)候注意一下,

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

相關(guān)文章

  • Yarn的安裝與使用詳細(xì)介紹

    Yarn的安裝與使用詳細(xì)介紹

    不知道大家有沒(méi)有覺(jué)察到Facebook近年大招頻出。Yarn是Facebook最近發(fā)布的一款依賴包安裝工具。Yarn是一個(gè)新的快速安全可信賴的可以替代NPM的依賴管理工具,Yarn正式發(fā)布沒(méi)幾天已經(jīng)迅速達(dá)到了數(shù)萬(wàn)贊,就可以知道大家苦NPM久已。這篇文章將詳細(xì)介紹Yarn的安裝與使用。
    2016-10-10
  • nodejs個(gè)人博客開(kāi)發(fā)第六步 數(shù)據(jù)分頁(yè)

    nodejs個(gè)人博客開(kāi)發(fā)第六步 數(shù)據(jù)分頁(yè)

    這篇文章主要為大家詳細(xì)介紹了nodejs個(gè)人博客開(kāi)發(fā)的數(shù)據(jù)分頁(yè),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-04-04
  • Node.js Koa2使用JWT進(jìn)行鑒權(quán)的方法示例

    Node.js Koa2使用JWT進(jìn)行鑒權(quán)的方法示例

    這篇文章主要介紹了Node.js Koa2使用JWT進(jìn)行鑒權(quán)的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-08-08
  • 原生nodejs使用websocket代碼分享

    原生nodejs使用websocket代碼分享

    本文給大家分享的是在原生的nodejs中如何使用websocket實(shí)現(xiàn)信息傳輸,非常實(shí)用,有需要的小伙伴可以參考下
    2018-04-04
  • nvm安裝步驟及使用方法

    nvm安裝步驟及使用方法

    nvm是一個(gè)管理nodejs版本的工具。在實(shí)際的開(kāi)發(fā)中,有些項(xiàng)目的開(kāi)發(fā)依賴需要低版本的nodejs運(yùn)行環(huán)境,有些則需要高版本的nodejs,此時(shí)我們就需要使用nvm來(lái)切換nodejs版本,接下來(lái)通過(guò)本文給大家講解nvm安裝步驟及使用方法,感興趣的朋友一起看看吧
    2023-01-01
  • Node.js模塊Modules的使用實(shí)戰(zhàn)教程

    Node.js模塊Modules的使用實(shí)戰(zhàn)教程

    這篇文章主要介紹了Node.js模塊Modules的使用,模塊就是一個(gè)聲明了裝飾器@Module()的類。裝飾器@Module()提供了元數(shù)據(jù),以便讓Nest組織應(yīng)用程序結(jié)構(gòu)
    2023-04-04
  • node+express+ejs使用模版引擎做的一個(gè)示例demo

    node+express+ejs使用模版引擎做的一個(gè)示例demo

    本篇文章主要介紹了node+express+ejs使用模版引擎做的一個(gè)示例demo,具有一定參考價(jià)值,有興趣的小伙伴可以了解一下
    2017-09-09
  • Nodejs使用SQL模糊查詢的過(guò)程詳解

    Nodejs使用SQL模糊查詢的過(guò)程詳解

    最近在改一個(gè)比較久的項(xiàng)目,是使用nodejs寫(xiě)的,但是對(duì)于長(zhǎng)期寫(xiě)java的后端開(kāi)發(fā)來(lái)說(shuō),還是有點(diǎn)難維護(hù),不過(guò)不改bug的話,就需要重新開(kāi)發(fā),所以本文介紹了NodeJs如何使用SQL模糊查詢,需要的朋友可以參考下
    2024-07-07
  • node-sass一直安裝不上、安裝失敗的原因分析

    node-sass一直安裝不上、安裝失敗的原因分析

    一個(gè)項(xiàng)目一直以來(lái)運(yùn)行都是正常的,今天運(yùn)行就突然報(bào)錯(cuò)了,錯(cuò)誤如下:?錯(cuò)誤大致意思就是node-sass安裝失敗,下面這篇文章主要給大家介紹了關(guān)于node-sass一直安裝不上、安裝失敗的原因分析,需要的朋友可以參考下
    2023-02-02
  • Node.js API詳解之 repl模塊用法實(shí)例分析

    Node.js API詳解之 repl模塊用法實(shí)例分析

    這篇文章主要介紹了Node.js API詳解之 repl模塊用法,結(jié)合實(shí)例形式分析了Node.js API中repl模塊基本功能、函數(shù)、使用方法及操作注意事項(xiàng),需要的朋友可以參考下
    2020-05-05

最新評(píng)論

墨江| 乳源| 高平市| 锡林浩特市| 铁岭市| 博兴县| 鱼台县| 萨迦县| 焦作市| 勃利县| 平谷区| 朔州市| 伊通| 长武县| 阳谷县| 辽宁省| 扎兰屯市| 正定县| 乳源| 阳江市| 深泽县| 林州市| 科尔| 湖口县| 罗城| 五大连池市| 荥阳市| 乐亭县| 延吉市| 得荣县| 疏附县| 启东市| 罗江县| 庆城县| 兰州市| 葵青区| 泗阳县| 滕州市| 罗江县| 凭祥市| 钦州市|