获取生成器函数的值,koa

Getting value of generator function, koa

我有一个函数可以从数据库中提取问题集合中的随机问题。

Game_Questions.js - 下面的 console.log 打印出正确的值(我需要的字符串),所以我认为 return 会让 yield 给出我回来了同样的价值。

exports.random_Question = function *() {
   yield Questions.findRandom().limit(1).exec(function(err,question){
     console.log("rand q: " + question[0].text);
     return question[0].text;
   });
}

Game.js:

var Game_Questions = require('./backend/Game_Questions');

这里我想从上面的代码片段 (Game_Questions.js) 中的 random_Question 函数访问 question[0].text 值。到目前为止我尝试了什么:

var found_Question = Game_Questions.random_Question();

var found_Question = Game_Questions.random_Question().next().value;

那两个 return [Object object] 在使用 JSON.stringify() 后显示该对象是: {"value":{"emitter":{"domain":null,"_events":{}},"emitted":{},"ended":true},"done":false}

我也试过使用co(function*()),但它也没有让我取出值。请帮助如何访问它?

您的语法很奇怪,但不确定这是否是 Koa 特有的?

因为Node.js是基于事件的,所以改用回调:

exports.random_Question = function(callback) {
    Questions.findRandom().limit(1).exec(function(err, question){
        callback(err, question);
    });
}

并使用它:

var Game_Questions = require('./backend/Game_Questions');
Game_Questions.random_Question(function(err, question) {
    console.log(question);
});

同样令人担忧的是,您的问题表明您在尝试引用 Game_Questions.randomQuestion() 而您的函数实际上被命名为 random_Question.

@remus 的答案是回调方法,而 Koa 被明确设计为放弃回调。因此,尽管它是非常好的代码并且适合 Express 应用程序,但它与 Koa 背后的设计理念完全不一致。

从外观上看,您使用的是 Mongoose,它从 4.0 版(2015 年 4 月发布)开始支持异步操作的承诺,应该允许采用 yield 方法。请注意,我假设您正在使用 Mongoose - 希望我没有错!

Here is some nice documentation on how Mongoose would fit nicely with koa.

所以首先要确保你使用的是支持使用 yield 的 Mongoose 版本。如果不是,您将不得不使用 @remus 方法或手动包装您的每个方法,以便它们产生兼容(即包装承诺)。

但是如果您使用的是兼容版本(4.0 及更高版本),那么您的代码将如下所示:

exports.random_Question = function *() {
  var result;

  try {
    result = yield Questions.findRandom().limit(1).exec();
  } catch(e) {
    console.log(e.stack);
    throw e;
  }

  console.log("rand q: " + result[0].text);
  return result[0].text;
}

请注意,我假设结果是一个基于您提供的代码的数组。

上面的例子不一定是生成器函数。 returns Promise 也可以是普通函数。所以也可以这样做:

exports.random_Question = function() {
  return Questions.findRandom()
    .limit(1)
    .exec()
    .then(function() {
      // I'm assuming mongoose assigns the value
      // being resolved in exec() to 'this'
      var question = this[0];
      console.log("rand q: " + question.text);
      return question.text;
    }).catch(function(e) {
      console.log(e.stack);
      throw e;
    });
}

所以对于 randomQuestion 函数来说,所有重要的是它可以由处理 Koa 应用程序流控制的 co 产生——检查 tj/co on GitHub 你可以产量。

所以最后回到 Koa 中间件,我们可以 yield 以完全相同的方式使用上述任一代码片段。所以我们会这样做:

var koa = require("koa");
var app = module.exports = koa();
var Game_Questions = require('./backend/Game_Questions');

app.use(function*() {
  var resultText;

  try {
      resultText = yield Game_Questions.random_Question();
  } catch(e) {
    this.throw(500);
  }

  this.body = resultText;
  this.status = 200;
});

app.listen(3000);

还有一点要注意,我对 mongoose 查询中的 findRandom 方法有点不确定,因为我不知道它是否能很好地与 mongoose 的 Promise 功能配合使用。就我个人而言,在重新引入 findRandom 之前,我会使用 yield 进行正常的猫鼬查询,只是为了确保它不会引起问题。

我的回答现在有点长,所以我就到此为止。