亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何在nodejs中使用next函數

發布時間:2021-03-17 14:59:51 來源:億速云 閱讀:322 作者:Leah 欄目:web開發

本篇文章給大家分享的是有關如何在nodejs中使用next函數,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

Next的作用

我們在定義express中間件函數的時候都會將第三個參數定義為next,這個next就是我們今天的主角,next函數主要負責將控制權交給下一個中間件,如果當前中間件沒有終結請求,并且next沒有被調用,那么請求將被掛起,后邊定義的中間件將得不到被執行的機會。

何時使用Next

從上邊的描述我們已經知道,next函數主要是用來確保所有注冊的中間件被一個接一個的執行,那么我們就應該在所有的中間件中調用next函數,但有一個特例,如果我們定義的中間件終結了本次請求,那就不應該再調用next函數,否則就可能會出問題,我們來看段代碼

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: {}
 });
});

發送請求"/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之后調用了next函數,雖然我們本次的請求已經被終止,但后邊的404中間件依舊會被執行,而后邊的中間件試圖去向res的headers中添加屬性值,所以就會拋出上邊的異常。

讀到這你可能會有個疑問,如果我不在res.send后邊調用next函數,那后邊定義的404中間件是不是永遠都不會被執行到。現在我們刪除res.send后邊next函數調用,發送請求"/xxx",我們就會發現404中間件被執行了,(ㄒoㄒ),這不是和我們之前說的矛盾了嗎,我們的自定義中間件沒有調用next,但后邊定義的中間件仍舊被執行了,這究竟是為什么呢。看來只能求助源碼了~~~

Next的內部機制

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的源碼,為了更容易說明問題,對代碼進行了刪減。從上邊的源碼可以發現,next函數內部有個while循環,每次循環都會從stack中拿出一個layer,這個layer中包含了路由和中間件信息,然后就會用layer和請求的path就行匹配,如果匹配成功就會執行layer.handle_request,調用中間件函數。但如果匹配失敗,就會循環下一個layer(即中間件)。

現在我們就能解釋上邊提出的問題了,為什么我們的自定義中間件中沒調用next函數,但后邊的404中間件仍舊會被執行到,因為我們請求的"/xxx"匹配不到我們注冊的"/a"路由中間件,所以while循環會繼續往下執行,匹配404中間件成功,所以會執行404中間件。

 注意:app.use注冊的中間件,如果path參數為空,則默認為"/",而path為"/"的中間件默認匹配所有的請求。

有一點需要特別指出,其實我們在定義路由中間件的時候函數的第三個參數next和我們定義非路由中間件的函數的第三個參數next不是同一個next,我們在上邊看到的是非路由中間件的next,而路由中間件的next函數是這樣的

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要簡單很多,它負責同一個路由的多個中間件的控制權的傳遞,并且它會接收一個參數"route",如果調用next(“route”),則會跳過當前路由的其它中間件,直接將控制權交給下一個路由。

最后有必要再說一說next(err),next(err)是如何將控制權傳遞到錯誤處理中間件的,從前邊的代碼我們知道,當調用next(err)是,express內部會調用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就是中間件函數,express會對fn的參數個數進行判斷,如果參數個數不等于4則認為不是錯誤處理中間件,則繼續調用next(err),這樣就會進入到下一個中間件函數,繼續進行參數個數判斷,如此方式一直到某個中間件函數的參數個數是4,就認為找到了錯誤處理中間件,然后執行此中間件函數。

以上就是如何在nodejs中使用next函數,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

雅江县| 浦城县| 平利县| 祁门县| 淮阳县| 梅州市| 花垣县| 日照市| 五家渠市| 腾冲县| 长岛县| 大城县| 绵竹市| 嘉兴市| 洪雅县| 苏尼特右旗| 南开区| 武汉市| 榕江县| 龙江县| 崇阳县| 揭阳市| 西和县| 天镇县| 松原市| 青阳县| 奈曼旗| 元朗区| 康保县| 临夏市| 黄龙县| 绥宁县| 六枝特区| 公安县| 龙井市| 封丘县| 克什克腾旗| 嵊泗县| 鄂温| 天全县| 蒙城县|