2017-06-02 90 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