node.js是否支持yield?

时间:2010-11-08 18:09:29

标签: node.js generator

有没有办法让generators进入node.js?

我目前正在使用回调伪装它们,但我必须记得检查我的生成器函数内部回调的响应,这会产生很多if (callback(arg) === false) return;

我想要像python中那样:

for p in primes():
  if p > 100: break
  do_something(p)

我在节点中这样做:

primes(function(p) {
  if (p > 100) return false;
  do_something(p)
});

coffeescript之类的东西可能会有所帮助吗?

10 个答案:

答案 0 :(得分:23)

答案 1 :(得分:8)

答案是“目前不是”,但马塞尔似乎是我的英雄。让我们希望这可以到达某个地方:

https://groups.google.com/forum/#!msg/nodejs/BNs3OsDYsYw/oCsWBw9AWC0J https://github.com/laverdet/node-fibers

答案 2 :(得分:4)

您可以在Node.js中使用生成器,但只能在0.11+中使用。 Node.js 0.12(稳定)现在可用。将--harmony_generators--harmony添加到节点的命令行参数以启用它。

使用Traceur,您可以将高级JavaScript编译为vanilla JavaScript。您可以为node.js创建一个即时执行此操作的加载程序。由于它运行并编译为vanilla JavaScript,因此它运行在node.js< 0.11以及浏览器。

Facebook开发了一款只支持生成器的轻型版本,名为Regenerator。它与Traceur的工作方式类似。

答案 3 :(得分:3)

显然不是目前的稳定版本。但是,您可以使用node-fiber + promise来实现相同的目标。

这是我的实施:

var fiber = require('fibers');

module.exports.yield = function (promise) {

    var currentFiber = fiber.current;
    promise
        .then(function (value) {
            currentFiber.run(value);
        })
        .otherwise(function (reason) {
            currentFiber.throwInto(reason);
        });

    return fiber.yield();
};
module.exports.spawn = function (makeGenerator) {
    fiber(function () {
        makeGenerator.apply(this, Array.prototype.slice.call(arguments, 1));
    }).run();
};

以及它如何工作的示例代码:(query.find返回一个promise)

        var generators = require('./utils/generators');
        var query = require('./utils/query');

        generators.spawn(function () {
            try {
                var field1 = generators.yield(query.find('user', { _id : '1' }));
                var field2 = generators.yield(query.find('user', { _id : '2' }));
                console.log('success', field1[0]._id, field2[0]._id);
            }
            catch (e) {
                console.error('error', e);
            }
        });

答案 4 :(得分:2)

您可以在http://fitzgen.github.com/wu.js/查看wu.js它有许多有趣的迭代器函数。

答案 5 :(得分:2)

是和否。

var myGen = (function () {
    var i = 0;
    return function () {
        i++; return i; }
})();
var i;
while ((i = myGen()) < 100 ) {
    do something; }

如您所见,您可以使用闭包实现类似的东西,但它没有本机生成器。

答案 6 :(得分:2)

v8项目成员最近接受了v8中issue提议的生成器 请投票,以使yield成真。

答案 7 :(得分:0)

2014年更新:Node现在支持回调。以下是2010年的帖子。


你应该使用回调。如果函数异步执行某些操作,您可能还需要一个连续回调(延续是一个坏词,因为它也意味着其他东西,但你明白我的意思。)

primes(function(p) {
  if (p > 100) return false // i assume this stops the yielding
  do_something(p)
  return true // it's also better to be consistent
}, function(err) { // fire when the yield callback returns false
  if (err) throw err // error from whatever asynch thing you did
  // continue...
})

更新了示例代码

我翻了它,所以它在完成时返回true(因为null,false和undefined,所有的评估都是false)。

function primes(callback) {
  var n = 1, a = true;
  search: while (a)  {
    n += 1;
    for (var i = 2; i <= Math.sqrt(n); i += 1)
      if (n % i == 0)
        continue search;
    if (callback(n)) return
  }
}

primes(function(p) {
  console.log(p)
  if (p > 100) return true
})

答案 8 :(得分:0)

我们正在gnode使用节点中的生成器&lt; 0.11.3 - https://github.com/TooTallNate/gnode

答案 9 :(得分:0)

是的,Node.js和JavaScript现在都具有同步迭代器(至少从Node v6开始)和异步迭代器(从Node v10开始):

具有同步输出的示例生成器/迭代器:

//import * as ABC from 'source file';

类似的异步生成器/迭代器。

// semi-pythonic like range
function* range(begin=0, end, step=1) {
  if(typeof end === "undefined") {
    end = begin;
    begin = 0;
  }
  for(let i = begin; i < end; i += step) {
    yield i;
  }
}

for(const number of range(1,30)) {
  console.log(number);
}

这里有很多值得探索的链接。以后我可能会用更多信息来更新此答案: