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 のようなものが役立つでしょうか?
答えは「現時点ではありません」ですが、マルセルは私のヒーローのようです。これがどこかに行くことを願いましょう:
https://groups.google.com/forum/#!msg/nodejs/BNs3OsDYsYw/oCsWBw9AWC0Jhttps://github.com/laverdet/node-fibers
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と同様に機能します。
どうやら現在の安定版にはない。ただし、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);
}
});
あなたは http://fitzgen.github.com/wu.js/ でwu.jsをチェックアウトするかもしれません==興味深いイテレータ関数がたくさんあります。
issue v8での生成元の提案は、v8プロジェクトメンバーによって最近承認されました。
_yield
を実現するために投票してください。
はいといいえ。
var myGen = (function () {
var i = 0;
return function () {
i++; return i; }
})();
var i;
while ((i = myGen()) < 100 ) {
do something; }
ご覧のとおり、クロージャーを使用して実装することもできますが、ネイティブジェネレーターはありません。
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.11.3のジェネレーターにはgnode
を使用しています- https://github.com/TooTallNate/gnode
はい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);
}
})();
ここで探索する多くの良いリンクがあります。私はおそらくこの回答を後で詳細に更新します: