Javascript 膝关节炎产生器 如何在膝关节炎中使用工作? 当我在app.use中设置一些生成器时,一切都很完美。 我怎么能在其他地方做同样的事情

Javascript 膝关节炎产生器 如何在膝关节炎中使用工作? 当我在app.use中设置一些生成器时,一切都很完美。 我怎么能在其他地方做同样的事情,javascript,node.js,koa,Javascript,Node.js,Koa,当我刚执行发电机手册时: var getRelationsList = function *() { var res = yield db.relations.find({}); console.log({'inside: ': res}); } console.log({'outside: ': getRelationsList().next()}); getRelationsList().next(); 我得到的只是{'outside:':{value:[Function],don

当我刚执行发电机手册时:

var getRelationsList = function *() {
  var res = yield db.relations.find({});
  console.log({'inside: ': res});
}
console.log({'outside: ': getRelationsList().next()});
getRelationsList().next();
我得到的只是{'outside:':{value:[Function],done:false}

我所期望的是:

{ 'outside: ': { value: {object_with_results}, done: false } }
{ 'inside: ': {object_with_results}
编辑

我这样更改了代码:

var getRelationsList = function *() {
  var res = yield db.relations.find({});
  console.log({'inside: ': res});
}
console.log({'outside ': co(getRelationsList)});
现在,在控制台日志内部显示的结果很好,但在控制台日志外部显示的只是空对象。
发电机必须由外部代码操作。 在引擎盖下,膝关节炎使用库来“运行”产生器。 以下是如何实现koa以外的目标:

var co = require('co');
var getRelationsList = function *() {
  var res = yield db.relations.find({});
  console.log({'inside: ': res});
}

co(getRelationsList).catch(function(err){});
我在JavaScript生成器上做了一个简短的屏幕广播,可以帮助您了解发生了什么:

++编辑

如果您使用生成器以更同步的方式编程(消除回调),那么您的所有工作都需要在生成器中完成,您应该使用类似co的库来执行生成器

下面是一个更详细的示例,说明如何手动与生成器交互。这应该有助于你理解你得到的结果

function * myGenerator () {
  var a = yield 'some value';
  return a;
}
var iterator = myGenerator();
// above line just instantiates the generator
console.log(iterator);
// empty object returned
// {}

var res1 = iterator.next();
// calling next() start the generator to either the 
// first yield statement or to return.
console.log(res1);
// res1 is an object with 2 attributes 
// { value: 'some value', done: false }
// value is whatever value was to the right of the first 
// yield statment 
// done is an indication that the generator hasn't run
// to completion... ie there is more to do
var toReturn = 'Yield returned: ' + res1.value;
var res2 = iterator.next(toReturn);
// calling next(toReturn) passes the value of 
// the variable toReturn as the return of the yield 
// so it's returned to the variable a in the generator 
console.log(res2);
// res2 is an object with 2 attributes 
// { value: 'Yield returned: some value', done: true }
// no further yield statements so the 'value' is whatever
// is returned by the generator.
// since the generator was run to completion 
// done is returned as true

发电机必须由外部代码操作。 在引擎盖下,膝关节炎使用库来“运行”产生器。 以下是如何实现koa以外的目标:

var co = require('co');
var getRelationsList = function *() {
  var res = yield db.relations.find({});
  console.log({'inside: ': res});
}

co(getRelationsList).catch(function(err){});
我在JavaScript生成器上做了一个简短的屏幕广播,可以帮助您了解发生了什么:

++编辑

如果您使用生成器以更同步的方式编程(消除回调),那么您的所有工作都需要在生成器中完成,您应该使用类似co的库来执行生成器

下面是一个更详细的示例,说明如何手动与生成器交互。这应该有助于你理解你得到的结果

function * myGenerator () {
  var a = yield 'some value';
  return a;
}
var iterator = myGenerator();
// above line just instantiates the generator
console.log(iterator);
// empty object returned
// {}

var res1 = iterator.next();
// calling next() start the generator to either the 
// first yield statement or to return.
console.log(res1);
// res1 is an object with 2 attributes 
// { value: 'some value', done: false }
// value is whatever value was to the right of the first 
// yield statment 
// done is an indication that the generator hasn't run
// to completion... ie there is more to do
var toReturn = 'Yield returned: ' + res1.value;
var res2 = iterator.next(toReturn);
// calling next(toReturn) passes the value of 
// the variable toReturn as the return of the yield 
// so it's returned to the variable a in the generator 
console.log(res2);
// res2 is an object with 2 attributes 
// { value: 'Yield returned: some value', done: true }
// no further yield statements so the 'value' is whatever
// is returned by the generator.
// since the generator was run to completion 
// done is returned as true

您的问题是多次调用getRelationsList()函数,这是不正确的

将代码更改为以下内容

var g = getRelationsList();
console.log('outside: ', g.next());
g.next(); //You get your console.log('inside: .... here

您的问题是多次调用getRelationsList()函数,这是不正确的

将代码更改为以下内容

var g = getRelationsList();
console.log('outside: ', g.next());
g.next(); //You get your console.log('inside: .... here

生成器是组织异步代码的强大工具,但它们不会神奇地等待异步代码运行

发生了什么事 让我们浏览一下您的代码,这样您就可以看到发生了什么:

getRelationsList
是一个生成器函数,调用该函数时返回一个新的生成器。此时,未调用生成器函数中的任何代码(尽管如果传递参数,则会设置它们)。然后在生成器上调用
.next
,开始执行生成器函数。它将一直执行,直到命中第一个yield语句,并返回一个对象,其中包含yield值和生成器的完成状态

到目前为止,您似乎了解其中的大部分内容,但生成器不会神奇地转换生成的值。当您输出
db.relations.find({})
时,您将得到
find
函数的返回值,我假设该函数是一个承诺或某种类型的表:

所以您的“外部”值是
{value:Promise,done:false}

内部
控制台.log
从未运行的原因是每次调用
getRelationsList()
时实际上都在创建一个新的生成器,因此当您在外部
控制台.log
之后再次调用
getRelationsList().next()
时,您正在创建一个新的生成器并调用next,所以它只执行到第一个屈服点,就像前一行的调用一样

为了完成执行,您必须在生成器的同一个实例上调用next两次:一次执行到产量,一次继续执行到函数结束

var gen = getRelationsList()
gen.next() // { value:Promise, done:false }
gen.next() // { value:undefined, done:true } (will also console.log inside)
var co = require('co');
var getRelationsList = function *() {
    var res = yield db.relations.find({});
    console.log({'inside: ': res});
    return res
}

co(getRelationsList).then(function(res) {
    console.log({'outside: ': res })
}).catch(function(err){
    console.log('something went wrong')
});
但是,您会注意到,如果运行此命令,内部的
console.log
将是
未定义的
。这是因为
yield
语句的值等于传递给以下
.next()
调用的值

例如:

var gen2 = getRelationsList()
gen2.next() // { value:Promise, done:false }
gen2.next(100) // { value:undefined, done:true } 
输出

{ inside:100 }
因为我们将100传递给了第二个
.next()
调用,它成为
yield db.relations.find({})
语句的值,该语句随后被分配给
res

下面是一个演示所有这些内容的链接:

解决方案 <膝关节炎的创建者使用一个小库,它基本上是产生承诺并等待它们完成,然后将解析值传递回生成器函数(使用<代码> .NEXT())/Cuff>函数,这样就可以以同步方式编写异步代码。 co将返回一个承诺,这将要求您调用
。然后
方法,以获取从生成器函数返回的值

var gen = getRelationsList()
gen.next() // { value:Promise, done:false }
gen.next() // { value:undefined, done:true } (will also console.log inside)
var co = require('co');
var getRelationsList = function *() {
    var res = yield db.relations.find({});
    console.log({'inside: ': res});
    return res
}

co(getRelationsList).then(function(res) {
    console.log({'outside: ': res })
}).catch(function(err){
    console.log('something went wrong')
});
co还允许您放弃其他生成器函数并等待其完成,因此您不必在每个级别都使用co包装东西,并在达到某种“顶级”之前处理承诺:

co(function *() {
    var list = yield getRelationsList()
      , processed = yield processRelations(list)
      , response = yield request.post('/some/api', { data:processed })
    return reponse.data
}).then(function(data) {
    console.log('got:', data)
})

生成器是组织异步代码的强大工具,但它们不会神奇地等待异步代码运行

发生了什么事 让我们浏览一下您的代码,这样您就可以看到发生了什么:

getRelationsList
是一个生成器函数,调用该函数时返回一个新的生成器。此时,未调用生成器函数中的任何代码(尽管如果传递参数,则会设置它们)。然后在生成器上调用
.next
,开始执行生成器函数。它将一直执行,直到命中第一个yield语句,并返回一个对象,其中包含yield值和生成器的完成状态

到目前为止,您似乎了解其中的大部分内容,但生成器不会神奇地转换生成的值。当您输出
db.relations.find({})
时,您将得到
find
函数的返回值,我假设该函数是一个承诺或某个t