web-dev-qa-db-ja.com

node.jsはyieldをサポートしていますか?

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 のようなものが役立つでしょうか?

48
Paul Tarjan
23
Diego Pino

答えは「現時点ではありません」ですが、マルセルは私のヒーローのようです。これがどこかに行くことを願いましょう:

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

8
Paul Tarjan

Node.jsでジェネレーターを使用できますが、0.11以降でのみ使用できます。 Node.js 0.12(安定版)が利用可能になりました。追加 --harmony_generatorsまたは--harmonyを有効にするには、nodeのコマンドラインパラメータを指定します。

Traceur を使用すると、高度なJavaScriptをVanilla JavaScriptにコンパイルできます。これをオンザフライで実行するnode.jsのローダーを作成できます。実行され、Vanilla JavaScriptにコンパイルされるため、node.js <0.11とブラウザーで実行されます。

Facebookは Regenerator と呼ばれるジェネレータのみをサポートする軽量バージョンを開発しました。 Traceurと同様に機能します。

4
DDS

どうやら現在の安定版にはない。ただし、node-fibers + 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);
            }
        });
3
Peeter

あなたは http://fitzgen.github.com/wu.js/ でwu.jsをチェックアウトするかもしれません==興味深いイテレータ関数がたくさんあります。

2
Alex Brown

issue v8での生成元の提案は、v8プロジェクトメンバーによって最近承認されました。
_yieldを実現するために投票してください

2
disfated

はいといいえ。

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

ご覧のとおり、クロージャーを使用して実装することもできますが、ネイティブジェネレーターはありません。

2
Not a Name

2014年更新:Nodeは現在コールバックをサポートしています。以下は2010年からの投稿です。


コールバックを使用する必要があります。関数が非同期で何かを行う場合は、継続コールバックも必要な場合があります(継続は別の意味でもあるため、Wordは不適切なWordですが、私の理解です)。

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
})
0
Tor Valamo

ノード<0.11.3のジェネレーターにはgnodeを使用しています- https://github.com/TooTallNate/gnode

0
manojlds

はいNode.jsとJavaScriptには、同期イテレータ(少なくともNode v6))と非同期イテレータ(Node v10))の両方が含まれるようになりました。

同期出力のジェネレーター/イテレーターの例:

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

同様の非同期ジェネレーター/イテレーター。

const timeout = (ms=1000) => new Promise((resolve, reject) => setTimeout(resolve, ms));

async function* countSeconds(begin=0, end, step=1) {
  if(typeof end === "undefined") {
    end = begin;
    begin = 0;
  }
  for(let i = begin; i < end; i += step) {
    yield i;
    await timeout(1000);
  }
}

(async () => {
  for await (const second of countSeconds(10)) {
    console.log(second);
  }
})();

ここで探索する多くの良いリンクがあります。私はおそらくこの回答を後で詳細に更新します:

0
John