2010-11-08 3 views
47

Есть ли способ получить generators в node.js?Поддерживает ли поддержка 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 может помочь?

+0

Coffeescript, скорее всего, не получит генераторы в ближайшее время: https://github.com/jashkenas/coffee-script/issues/issue/983#issue/983/comment/639738 – Amir

+1

Также обратите внимание, что JavaScript использует camelCase для функций, то есть 'doSomething', а не' do_something' – mikemaccana

ответ

23
+4

, но их текущий verion 'v0.10.24', я в замешательстве. – Michelle

+2

Последняя стабильная версия - v.0.10.24, но вы всегда можете получить неустойчивый выпуск [здесь] (http://nodejs.org/dist/) (в настоящее время v0.11.10). Релизы всегда объявляются в узле [blog] (http://blog.nodejs.org/release/) (с изменением журнала). Документы v0.11.10 [здесь] (http://nodejs.org/dist/v0.11.10/docs/api/). Это не должно было быть трудно найти с [домашней страницы Nodejs.org] (http://nodejs.org)> [Загрузки] (http://nodejs.org/download/)> [Другие выпуски] (http://nodejs.org/dist/). –

+0

Я не могу заставить их работать, даже с флагом '--harmony' в узле v0.10.29. – mpen

0

Обновление 2014: Узел теперь поддерживает обратные вызовы. Ниже следует сообщение с 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 
}) 
+0

Но тогда моя функция 'primes' засорена' if (callback (arg) === false) return; ' а не просто «yield arg». Это должно быть так уродливо? –

+1

'do {/ * установить данные обратного вызова * /} while (callback (arg)); continue() '? Помните, что это не так важно, как выглядит внутри функции, если интерфейс и выход хороши. –

+0

oh, и относительно вашей функции primes (я предполагаю, что вы делаете сложную вложенность там), вам нужно закодировать его таким образом, чтобы он мог отбросить все, перейти к обратному вызову, а затем начать снова на следующей итерации (используя временные переменные для сохранения состояния), или вам просто нужно будет жить с несколькими линиями обратного вызова. –

2

Да и нет.

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

Как вы видите, вы можете реализовать что-то вроде использования с закрытием, но у него нет встроенных генераторов.

2

issue предложение генераторов в v8 недавно было принято участником проекта v8.
Проголосуйте, чтобы сделать yield сбудется.

4

Вы можете использовать генераторы в Node.js, но только в 0.11+. Теперь доступен Node.js 0.12 (стабильный). Добавьте --harmony_generators или --harmony в параметры командной строки узла, чтобы включить его.

С помощью Traceur вы можете скомпилировать JavaScript в JavaScript. Вы можете сделать загрузчик для узла.js, который делает это на лету. Поскольку он работает и компилируется на ванильный JavaScript, он запускается в node.js < 0.11, а также в браузере.

Facebook разработал более легкую версию, которая поддерживает только генераторы, называемые Regenerator. Он работает аналогично Traceur.

3

Видимо, не в текущей стабильной версии. Тем не менее, вы можете достичь того же уровня, что и узловые волокна + обещания.

Вот моя реализация:

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 возвращает обещание)

 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); 
      } 
     }); 
+0

не могли бы вы также разместить исходный код для запроса? будет ли он работать с любой системой обратного вызова? – kroe