2017-06-02 91 views
0

我有Express.js實例和幾個我想在某些函數中包裝的路由。例如:Express.js - 在「裝飾器」中包裝每個中間件/路由

const wrapper = (route) => { 
    return (req, res, next) => { 
    let result = route(req, res, next); 

    // do some independent processing 
    } 
}; 

app.get('/', wrapper((req, res, next) => { 
    // respond to request somehow 
})); 

雖然這工作得很好,我不喜歡這個主意,顯式調用wrapper路線或中間件需要這樣的處理。

有沒有什麼辦法能夠包裹在某些包裝每一個需要的路由/中間件(假設wrapper功能,可以檢查該路由/中間件需要被包裹)隱式(通過Express.js擴展,猴子打補丁或一些特殊中間件)?

UPDATE:

更多固體例子。假設我想製作一個async路由器功能。但我不想在每個路線功能中發現錯誤。所以我包裹起來:

const wrapper = func => (req, res, next) => { 
    const promise = func(req, res, next); 

    if (promise.catch) { 
    promise.catch(err => next(err)); 
    } 

    next(); 
}; 

app.get('/one', wrapper(async (req, res, next) => { 
    // respond to request somehow 
})); 

app.get('/two', wrapper(async (req, res, next) => { 
    // respond to request somehow 
})); 

app.get('/three', wrapper(async (req, res, next) => { 
    // respond to request somehow 
})); 

// and so on... 

app.use((err, req, res, next) => { 
    // do something with intercepted error 
}); 

這明確wrapper所有455元其實是我想擺脫的東西。

+0

是您運行一些代碼的最終目標上REQ添加的東西? – robertklep

+0

不,我的目標是裝飾路由器功能,這樣我就可以得到直接的響應結果(例如,返回Promise),並用它做一些事情。 – Nevertheless

回答

2

原來是PITA的一點,因爲最終,Express並不傳播路由處理函數的返回值。

這是我想出了(猴子補丁):

const Layer   = require('express/lib/router/layer'); 
const handle_request = Layer.prototype.handle_request; 

Layer.prototype.handle_request = function(req, res, next) { 
    if (! this.isWrapped && this.method) { 
    let handle = this.handle; 
    this.handle = function(req, res, next) { // this is basically your wrapper 
     let result = handle.apply(this, arguments); 
     // do some independent processing 
     return result; 
    }; 
    this.isWrapped = true; 
    } 
    return handle_request.apply(this, arguments); 
}; 

我會使用類似的方法爲express-promise-router雖然可能表明,它實現了一個簡易替換爲快遞Router。但是,這並不是隱含的。

+0

感謝您的回答。但這並不僅僅涉及路由器功能的返回值。讓我用更明確的例子更新我的功能。 – Nevertheless

+0

@KidBinary使用提供的示例來實現你想要的('if(result.catch){...}')是非常簡單的。顯然,你也可以將它改寫成一個實用函數來隱藏血腥的細節。 – robertklep

+0

我明白了。再次謝謝你,真的很遺憾這個問題*是* PITA:) – Nevertheless

0

爲什麼不使用next()?

您可以在發送響應像

app.get('/', (req, res, next) => { 
    req.somestupidfieldthatidontevenknowwhyinamedthisway = 42; 
    next(); 
}); 

app.get('/', (req, res, next) => { 
    //req.somestupidfieldthatidontevenknowwhyinamedthisway is now accessible as 42 
    var valueFromPreviousMiddleware = req.somestupidfieldthatidontevenknowwhyinamedthisway; 
    ..... 
}); 
+0

因爲這實際上不是重點。讓我更新我的問題。 – Nevertheless