ES6生成器可以产生正常传递给回调/承诺的数据吗?

时间:2016-01-22 15:49:51

标签: javascript generator ecmascript-6

所以,如果你有这样的功能:

function* queryDB(query){
    yield db.collection.find(query);
}

根据我的理解,它会产生db.collection.find()返回的内容,所以说它返回一个promise,然后queryDB()应该返回一个带有promise作为值的iterable,所以可以使用co这样的东西巩固承诺产生的承诺。有没有办法在不修改db.collection.find()的情况下产生传递给该承诺的内容,以便我可以使用for-of循环来迭代数据库中的结果?

要清除

我在问我是否可以获取传递给函数的参数传递给promise的.then()。如在

queryDB().then(function(<values>)

但我得到<values>的迭代器。

1 个答案:

答案 0 :(得分:1)

只能在发电机内做这个。

function* queryDB(query) {
  // Here is synchrous-like code!
  var rows = yield db.collection.find(query);

  var sum = 0;

  // Use the rows synchrously
  for (var x of rows) {
    sum += x;
  }

  return sum;
}

var sumPromise = doM(queryDB('query example'));

sumPromise.then(console.log.bind(console));

请参阅demo(我建议您使用此功能,看看它在不同情况下会返回什么内容,并且会很清楚)。

无法做到

for (var x of db.collection.find(query))
  ...

或者:

for (var x of queryDB('some query'))
  ...

就像:

for (var x of (new Promise(...)))
  ...

您的生成器/包装器将返回一个承诺。您只能then使用它。

无法做到

function* queryDB(query) {
  db.collection.find(query).then(function(values) {
      yield values;
  });
}

对最后的说明:

编译器将如何看到此代码:

function* queryDB(query) {
  db.collection.find(query).then(anonymousFunction);
}

并且anonymousFunction不是生成器,所以你不能在那里写yield。另外,Promise中的then不期望生成器。

另一方面,如果你想使用for (var x in queryDB()),编译器希望从queryDB()返回一个数组。如果你的queryDB()是异步的,它将返回一个类似Promise的界面。

如果您切换到更多功能样式,您可以写:

 forEach(queryDB(), function(item) {
    // action on item
 });

如果您现在承诺的值是数组,则可以执行reducemap。但在这种情况下,您不需要发电机。

doM实施:

function doM(gen) {
  function step(value) {
    var result = gen.next(value);
    if (result.done) {
      return result.value;
    }
    return result.value.then(step);
  }
  return step();
}

来源:Monads in JavaScript

forEach实施:

function forEach(promise, callback) {
  return promise.then(function(iterable) {
    for (var x of iterable) {
      callback(x);
    }
  });
}