2015-07-22 42 views
1

我有一个函数,从数据库中抽出一个来自Questions集合的随机问题。获取发电机功能的价值,koa

Game_Questions.js - 下面的console.log输出正确的值(我需要的字符串),所以我认为返回会让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'); 

在这里,我想从random_Question功能从代码片段访问上述(Game_Questions.js)question[0].text值。我试过到目前为止:

var found_Question = Game_Questions.random_Question();

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

这两个回报[Object对象],它透过JSON.stringify()后显示的对象是: {"value":{"emitter":{"domain":null,"_events":{}},"emitted":{},"ended":true},"done":false}

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

+1

您将始终需要使用回调,因为它是异步的。 'co(Game_Questions())'应该为iirc返回一个承诺。 – Bergi

回答

2

@remus的回答是一种回调方法,Koa明确地设计了回调函数。因此,虽然它是完美的代码,并且适合Express应用程序,但完全与Koa背后的设计理念背道而驰。

从它的外观来看,您使用的是Mongoose,它支持从4.0版本开始的异步操作承诺(2015年4月发布),它应该允许采取收益方法。注意我正在做一个与猫鼬一起工作的假设 - 我希望我没有错!

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

所以首先请确保您使用的版本支持使用产量猫鼬的。如果不是,你将不得不使用@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; 
} 

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

上述示例不一定必须是生成器函数。它也可以是返回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功能所有重要的是,它可以通过co它处理兴亚应用程序的流量控制可以产生 - 检查tj/co on GitHub你可以在不同的对象产量。因此,最终回到Koa中间件,我们可以用yieldyield上述任一代码片段以完全相同的方式。所以我们应该这样做:

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); 

别的东西要注意的是,我有点不确定的猫鼬查询findRandom方法,因为我不知道这是否与猫鼬的承诺特点播放好听。就个人而言,我会在重新引入findRandom之前使用yield来正常使用猫鼬查询,以确保它不会引起问题。

我的答案在这一点上已经有点长了,所以我会把它留在那里。

+0

嗨@Peadar Doyle,你是对的,我在我的项目中运行Mongoose,它是4.0.7版本,所以它应该支持yield。我之所以使用'question [0] .text'是因为'questions'是一个对象数组,我想要“文本”的价值,所以我想我可以这样访问它。我试过你的解决方案,但我不知道我应该如何在其他文件中调用这个函数。 'Game_Questions.random_Question()。next()。value;'和'var Game_Questions.random_Question();'不好运作 – jwitos

+1

我已经更新了我的答案。了解coa,'generators'和'promise'在Koa中的工作方式是学习它最棘手的挑战。不幸的是,这些也提供了Koa的所有优点;所以你不能掩饰它们。 –

+0

感谢您提供非常丰富的答案。我现在可以看到我现在面临的问题 - 我的示例(Game.js文件)只是整个方法的一个片段,其中包含许多标准(非生成器)函数。我知道我应该用koa标准制作它们,所以我现在不会面临这个问题。我会尝试重写我的功能,我会用结果更新你。非常感谢 – jwitos

1

你的语法很奇怪,但不确定这是否特定于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

+0

嗨,非常感谢@remus,我犯了可怕的语法错误,所以是的,应该有random_Question **,但**它让我回到'[Object object]'。当我尝试你的解决方案时,_questionText_未定义,可能是因为console.log在'random_Question()'之前运行。 – jwitos

+1

如果'question [0] .text'不存在,那会导致未定义。在'findRandom()'的回调函数中记录'question'时会发生什么? – brandonscript

+0

然后它会记录正确的值 - 无论是在您的解决方案和我的例子与发电机功能。 @remus – jwitos