十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
本篇文章給大家分享的是有關(guān)如何在nodejs中使用next函數(shù),小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

在輝縣等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強發(fā)展的系統(tǒng)性、市場前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務理念,為客戶提供成都網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計 網(wǎng)站設(shè)計制作定制網(wǎng)站設(shè)計,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),成都品牌網(wǎng)站建設(shè),網(wǎng)絡(luò)營銷推廣,成都外貿(mào)網(wǎng)站制作,輝縣網(wǎng)站建設(shè)費用合理。
Next的作用
我們在定義express中間件函數(shù)的時候都會將第三個參數(shù)定義為next,這個next就是我們今天的主角,next函數(shù)主要負責將控制權(quán)交給下一個中間件,如果當前中間件沒有終結(jié)請求,并且next沒有被調(diào)用,那么請求將被掛起,后邊定義的中間件將得不到被執(zhí)行的機會。
何時使用Next
從上邊的描述我們已經(jīng)知道,next函數(shù)主要是用來確保所有注冊的中間件被一個接一個的執(zhí)行,那么我們就應該在所有的中間件中調(diào)用next函數(shù),但有一個特例,如果我們定義的中間件終結(jié)了本次請求,那就不應該再調(diào)用next函數(shù),否則就可能會出問題,我們來看段代碼
app.get('/a', function(req, res, next) {
res.send('sucess');
next();
});
// catch 404 and forward to error handler
app.use(function(req, res, next) {
console.log(404);
var err = new Error('Not Found');
err.status = 404;
next(err);
});
app.use(function(err, req, res, next) {
res.status(err.status || 500);
res.render('error', {
message: err.message,
error: {}
});
});發(fā)送請求"/a",控制臺打印日志如下:
404 GET /a 500 6.837 ms - - Error: Can't set headers after they are sent. at ServerResponse.OutgoingMessage.setHeader (_http_outgoing.js:345:11)
為什么代碼會拋異常呢,就是因為我們在res.send之后調(diào)用了next函數(shù),雖然我們本次的請求已經(jīng)被終止,但后邊的404中間件依舊會被執(zhí)行,而后邊的中間件試圖去向res的headers中添加屬性值,所以就會拋出上邊的異常。
讀到這你可能會有個疑問,如果我不在res.send后邊調(diào)用next函數(shù),那后邊定義的404中間件是不是永遠都不會被執(zhí)行到?,F(xiàn)在我們刪除res.send后邊next函數(shù)調(diào)用,發(fā)送請求"/xxx",我們就會發(fā)現(xiàn)404中間件被執(zhí)行了,(ㄒoㄒ),這不是和我們之前說的矛盾了嗎,我們的自定義中間件沒有調(diào)用next,但后邊定義的中間件仍舊被執(zhí)行了,這究竟是為什么呢??磥碇荒芮笾创a了~~~
Next的內(nèi)部機制
function next(err) {
... //此處源碼省略
// find next matching layer
var layer;
var match;
var route;
while (match !== true && idx < stack.length) {
layer = stack[idx++];
match = matchLayer(layer, path);
route = layer.route;
if (typeof match !== 'boolean') {
// hold on to layerError
layerError = layerError || match;
}
if (match !== true) {
continue;
}
... //此處源碼省略
}
... //此處源碼省略
// this should be done for the layer
if (err) {
layer.handle_error(err, req, res, next);
} else {
layer.handle_request(req, res, next);
}
}上邊就是express中next的源碼,為了更容易說明問題,對代碼進行了刪減。從上邊的源碼可以發(fā)現(xiàn),next函數(shù)內(nèi)部有個while循環(huán),每次循環(huán)都會從stack中拿出一個layer,這個layer中包含了路由和中間件信息,然后就會用layer和請求的path就行匹配,如果匹配成功就會執(zhí)行l(wèi)ayer.handle_request,調(diào)用中間件函數(shù)。但如果匹配失敗,就會循環(huán)下一個layer(即中間件)。
現(xiàn)在我們就能解釋上邊提出的問題了,為什么我們的自定義中間件中沒調(diào)用next函數(shù),但后邊的404中間件仍舊會被執(zhí)行到,因為我們請求的"/xxx"匹配不到我們注冊的"/a"路由中間件,所以while循環(huán)會繼續(xù)往下執(zhí)行,匹配404中間件成功,所以會執(zhí)行404中間件。
注意:app.use注冊的中間件,如果path參數(shù)為空,則默認為"/",而path為"/"的中間件默認匹配所有的請求。
有一點需要特別指出,其實我們在定義路由中間件的時候函數(shù)的第三個參數(shù)next和我們定義非路由中間件的函數(shù)的第三個參數(shù)next不是同一個next,我們在上邊看到的是非路由中間件的next,而路由中間件的next函數(shù)是這樣的
function next(err) {
if (err && err === 'route') {
return done();
}
var layer = stack[idx++];
if (!layer) {
return done(err);
}
if (layer.method && layer.method !== method) {
return next(err);
}
if (err) {
layer.handle_error(err, req, res, next);
} else {
layer.handle_request(req, res, next);
}
}這個next比上邊的那個next要簡單很多,它負責同一個路由的多個中間件的控制權(quán)的傳遞,并且它會接收一個參數(shù)"route",如果調(diào)用next(“route”),則會跳過當前路由的其它中間件,直接將控制權(quán)交給下一個路由。
最后有必要再說一說next(err),next(err)是如何將控制權(quán)傳遞到錯誤處理中間件的,從前邊的代碼我們知道,當調(diào)用next(err)是,express內(nèi)部會調(diào)用layer.handle_error,那我們來看看它的源碼
Layer.prototype.handle_error = function handle_error(error, req, res, next) {
var fn = this.handle;
if (fn.length !== 4) {
// not a standard error handler
return next(error);
}
try {
fn(error, req, res, next);
} catch (err) {
next(err);
}
};代碼中的fn就是中間件函數(shù),express會對fn的參數(shù)個數(shù)進行判斷,如果參數(shù)個數(shù)不等于4則認為不是錯誤處理中間件,則繼續(xù)調(diào)用next(err),這樣就會進入到下一個中間件函數(shù),繼續(xù)進行參數(shù)個數(shù)判斷,如此方式一直到某個中間件函數(shù)的參數(shù)個數(shù)是4,就認為找到了錯誤處理中間件,然后執(zhí)行此中間件函數(shù)。
以上就是如何在nodejs中使用next函數(shù),小編相信有部分知識點可能是我們?nèi)粘9ぷ鲿姷交蛴玫降?。希望你能通過這篇文章學到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。