[!NOTE]
中間件其是一個函數,在響應發送以前對請求進行一些操做面試
function middleware(req,res,next){ // 作該乾的事 // 作完後調用下一個函數 next(); }
這個函數有些不太同樣,它還有一個next參數,而這個next也是一個函數,它表示函數數組中的下一個函數express
[!NOTE]
express內部維護一個函數數組,這個函數數組表示在發出響應以前要執行的全部函數,也就是中間件數組數組
使用app.use(fn)後,傳進來的fn就會被扔到這個數組裏,執行完畢後調用next()方法執行函數數組裏的下一個函數,若是沒有調用next()的話,就不會調用下一個函數了,也就是說調用就會被終止架構
function express() { // 函數數組用於存放全部的中間件函數 let fns = []; let app = function(req, res) { let i = 0; function next() { // 取出數組中的下一個函數 let task = fns[i++]; // 若是函數存在的u啊 if (task) { // 就先去執行這個用戶自定義的函數裏面的業務邏輯(每次把當前的next繼續向後傳遞) task(req, res, next); } } // 用戶首次調用的執行第一個 next(); } // 使用use的時候就把用戶指定的這個函數放入到一個函數數組裏面去 app.use = function(task) { fns.push(task); } return app; }
function fn1(next) { next(); } function fn2(next) { next(); } function fn3(next) { next(); } // 相似於一個異步的迭代器 function nextRegister(...tasks) { let i = 0; function next() { let task = tasks[i]; if (!task || typeof task !== 'function') { return ; } task(next); } // 第一次調用 next(); } // 開始註冊三個異步函數 nextRegister(fn1, fn2, fn3);
[!NOTE]
關鍵在於解釋清楚對路由中間件的理解,能夠以koa的洋蔥模型講解爲例。app