在SailsJS中使用ES6 Generator功能

时间:2016-03-03 01:49:22

标签: node.js sails.js ecmascript-6

我喜欢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?

4 个答案:

答案 0 :(得分:3)

你可以使用它,事实上如果我们都使用这种风格它会很棒,它会在你的代码中增加很多可读性和灵活性(不再有回调地狱), 但这不是使用它的方式

正如@Cohars所说,帆希望功能作为控制器动作,你不能像Koa那样通过生成器,但这并不妨碍你使用它们,那就是那个一个生成器本身是非常无用的,你需要一个调用它并迭代它的函数我相信koa在框架级别为你做这个,但你在库级别有一些选项,比如coyortus/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()

一样,如果你正在使用coffeescript,这是一个完美的匹配

<强>更新

我创建了一个包装器,如果您使用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有什么帮助。如果你真的想使用生成器,你应该尝试使用基于它的Koaseveral 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();
    });
  });
});