我喜欢nodejs中的生成器。它们帮助nodejs看起来更像服务器端代码。我试图在我的Sails应用程序中使用生成器。这是我的控制器,当我访问' get / hi':
时,它可以正常工作/**
* FooController
*
* @description :: Server-side logic for managing foos
* @help :: See http://sailsjs.org/#!/documentation/concepts/Controllers
*/
module.exports = {
hi: function (req, res){
return res.send("Hi there!");
}
};
然而,当我将hi动作改为生成器函数时......
module.exports = {
hi: function* (req, res){
return res.send("Hi there!");
}
};
此操作永远不会返回响应。喜欢它等着什么。如何在SailsJS控制器中使用ES6生成器,实际上是所有Sails?
答案 0 :(得分:3)
你可以使用它,事实上如果我们都使用这种风格它会很棒,它会在你的代码中增加很多可读性和灵活性(不再有回调地狱), 但这不是使用它的方式。
正如@Cohars所说,帆希望功能作为控制器动作,你不能像Koa那样通过生成器,但这并不妨碍你使用它们,那就是那个一个生成器本身是非常无用的,你需要一个调用它并迭代它的函数我相信koa在框架级别为你做这个,但你在库级别有一些选项,比如co或yortus/asyncawait/这是我使用的,因为作为函数实现的节点光纤比es6生成器更灵活(尽管它们几乎相同)并且我将在一秒内向您展示原因
所以这就是你如何使用它:
首先npm install co
并在控制器中要求它,或者在config / bootstrap.js中将其添加为全局,因为您将大量使用它。完成后,您可以在控制器中使用它。
module.exports = {
hi: function(req, res){
co(function* (){
// And you can use it with your models calls like this
let user = yield User.findOne(req.param('id'))
return res.send("Hi there" + user.name + "!");
})
}
};
那是
现在如果您更喜欢使用 async / await ,它非常相似,就像这样:
module.exports = {
hi: function(req, res){
async(function(){
// Since await is a function, you can access properties
// of the returned values like this which is nice to
// access object properties or array indices
let userName = await(User.findOne(req.param('id'))).name
return res.send("Hi there" + userName + "!");
})();
}
};
有一个警告但是,如果你通过this
调用你控制器的其他方法,请记住,如果你使用async /它们将引用生成器fn或传递的常规fn等待,所以一定要保存它的上下文,或者因为你已经在使用es6语法,你可以使用带有async / await的胖箭头,遗憾的是不能用co,因为没有胖箭头版本的生成器(..你?)< / p>
所以它会是这样的:
module.exports = {
hi: function(req, res){
async(() => {
let params = this._parseParams(req);
let userName = await(User.findOne(params.id)).name
return res.send("Hi there" + userName + "!");
})();
},
_parseParams: function(req){
let params = req.allParams()
// Do some parsing here...
return params
}
};
我几个月来一直在使用第二种方法,并且工作得很好,我也尝试过使用co也可以工作,我只是更喜欢async / await模块(并且应该是因为你的sintax就像do async => await User.find()
<强>更新强>
我创建了一个包装器,如果您使用yortus async / await,或者检查源代码并根据需要修改它以使用co或其他东西,您可以使用它。
以下是链接https://www.npmjs.com/package/async-handler,在alpha版本中,但我在自己的应用中使用并按预期工作,如果没有提交问题。
有了这个,例子就是这样:
module.exports = {
hi: asyncHandler((req, res)->{
let params = this._parseParams(req);
let userName = await(User.findOne(params.id)).name
return res.send("Hi there" + userName + "!");
}),
_parseParams: function(req){
let params = req.allParams()
// Do some parsing here...
return params
}
};
使用此处理程序,您可以获得额外的好处,即如果没有被try / catch捕获,可以在sails上正确传播async / promise错误
答案 1 :(得分:0)
Sails期望这里有常规功能,而不是发电机。也许你可以看看co,但不确定它对Sails有什么帮助。如果你真的想使用生成器,你应该尝试使用基于它的Koa的several frameworks
答案 2 :(得分:0)
我这样做的方式是这样的:
const Promise = require('bluebird');
module.exports = {
hi: Promise.coroutine(function* (req, res) {
let id = req.params('id'),
userName;
try {
userName = yield User.findOne(id).name;
}
catch (e) {
sails.log.error(e);
return res.serverError(e.message);
}
return res.ok(`Hi there ${userName}!`);
})
}
效果很好。您只需要确保从控制器调用的任何函数都会返回承诺。
答案 3 :(得分:0)
将此代码放入bootstrap.js
,每件事情都像魅力一样!
var _ = require('lodash');
var coExpress = require('co-express');
sails.modules.loadControllers(function (err, modules) {
if (err) {
return callback(err);
}
sails.controllers = _.merge(sails.controllers, modules);
// hacking every action of all controllers
_.each(sails.controllers, function(controller, controllerId) {
_.each(controller, function(action, actionId) {
actionId = actionId.toLowerCase();
console.log('hacking route:', controllerId, actionId);
// co.wrap,generator => callback
action = coExpress(action);
sails.hooks.controllers.middleware[controllerId][actionId] = action;
});
});
// reload routes
sails.router.load(function () {
// reload blueprints
sails.hooks.blueprints.initialize(function () {
sails.hooks.blueprints.extendControllerMiddleware();
sails.hooks.blueprints.bindShadowRoutes();
callback();
});
});
});