问题描述
我正在尝试节点0.12中的一些和声功能,特别是尝试新的生成器功能。我正在使用co(v4),bluebird和express(v4),这样做:
I'm trying out some of the harmony features in node 0.12, in particular trying out the new generators feature. I'm doing this with co (v4), bluebird and express (v4), something like this:
// ...
var fs = bluebird.promisifyAll(require('fs'));
// ...
app.post('/test', co.wrap(function* (req, res, next) {
var contents = yield fs.readFileAsync('/etc/hosts', 'utf8');
return res.send(contents);
}));
// ...
根据其文档,co.wrap返回一个正常的函数这将从给定的生成器函数返回一个承诺。
According to its documentation, co.wrap returns a normal function that returns a promise from the given generator function.
这是迄今为止工作正常,但我不知道如果a)我没有泄漏内存等待返回的承诺的结果,并且b)如果我可能会丢失在我的生成器函数中抛出的异常,或者它使用的一个模块。
This is working fine so far, but what I'm not sure is if a) I'm leaking memory by not 'waiting' for the returned promise's result and b) If I might lose an exception thrown in my generator function, or one of the modules used by it.
这是一个好办法你看到有什么问题吗?
Is this a good approach? Do you see anything wrong with it?.
推荐答案
你的方法的问题是,如果你的生成器函数会抛出一些异常,它不会传递到下一个中间件。所以你会失去它。您可以使用蓝鸟的功能来实现你自己的简单的 co 包装器,这将在express中运行得很好:
The problem with your approach is that if your generator function will throw some exception, it will not be passed to next middleware. So you will lose it. You can use bluebird's Promise.coroutine
function to implement your own simple co
wrapper, which will be working well in express:
// module: ../helpers/co.js
var Promise = require('bluebird');
var co = Promise.coroutine;
module.exports = function(gen) {
var coGen = co(gen);
function handle_error(err, req, res, next) {
return coGen.apply(this, arguments).catch(next);
}
function handle_request(req, res, next) {
return coGen.apply(this, arguments).catch(next);
}
return gen.length > 3 ? handle_error : handle_request;
};
UPD :我已经改变了一些实现。现在它考虑到传递给生成器的数量或参数:如果> 3,那么将使用错误处理程序,否则 - 请求处理程序。对于快递(请参阅源代码和)
UPD: I have changed the realization a little. Now it takes into account the number or arguments passed into the generator: if > 3 then error handler will be used, otherwise - request handler. It's important for express (look in the source code here and here)
现在您可以在代码中使用它:
Now you can use it in your code:
// module: your/router.js
// ...
var co = require('../helpers/co');
var fs = bluebird.promisifyAll(require('fs'));
// ...
app.post('/test', co(function* (req, res, next) {
var contents = yield fs.readFileAsync('/etc/hosts', 'utf8');
return res.send(contents);
}));
// ...
UPD 这是解决方案表示版本为< = 4.x.最有可能表达5.x ,所以你可以使用蓝鸟的 Promis.coroutine
没有任何花哨的包装器:
UPD This is solution for express with version <= 4.x. Most likely express 5.x will support promises, so you'll can use just bluebird's Promis.coroutine
without any fancy wrappers:
// module: your/router.js
// ...
var fs = bluebird.promisifyAll(require('fs'));
var co = bluebird.coroutine;
// ...
app.post('/test', co(function*(req, res, next) {
var contents = yield fs.readFileAsync('/etc/hosts', 'utf8');
return res.send(contents);
}));
// ...
这篇关于发电机功能用蓝鸟和co的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!