web-dev-qa-db-fra.com

Node.js prend-il en charge le rendement?

Existe-t-il un moyen d'obtenir générateurs dans node.js?

Je les simule actuellement avec des callbacks, mais je dois me rappeler de vérifier la réponse du callback à l'intérieur de ma fonction de générateur qui crée beaucoup de if (callback(arg) === false) return;

Je veux quelque chose comme en python:

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

ce que je fais dans un nœud comme celui-ci:

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

Peut-être que quelque chose comme coffeescript pourrait vous aider?

48
Paul Tarjan
23
Diego Pino

La réponse est "pas actuellement" mais Marcel semble être mon héros. Espérons que cela aille quelque part:

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

8
Paul Tarjan

Vous pouvez utiliser des générateurs dans Node.js, mais uniquement dans la version 0.11+. Node.js 0.12 (stable) est maintenant disponible. Ajouter --harmony_generators ou --harmony aux paramètres de ligne de commande du nœud pour l'activer.

Avec Traceur , vous pouvez compiler du JavaScript avancé en JavaScript vanille. Vous pouvez créer un chargeur pour node.js qui le fait à la volée. Comme il s'exécute et se compile en JavaScript Vanilla, il s'exécute dans node.js <0.11 ainsi que dans le navigateur.

Facebook a développé une version plus légère qui ne prend en charge que les générateurs, appelée Regenerator . Cela fonctionne de la même manière que Traceur.

4
DDS

Apparemment pas dans la version stable actuelle. Vous pouvez cependant réaliser la même chose en utilisant des nœuds-fibres + des promesses.

Voici ma mise en œuvre:

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

Et un exemple de code sur son fonctionnement: (query.find renvoie une promesse)

        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

Vous pouvez consulter wu.js à http://fitzgen.github.com/wu.js/ Il a beaucoup de fonctions d'itérateur intéressantes.

2
Alex Brown

Le issue proposant des générateurs dans la v8 a récemment été accepté par un membre du projet v8.
Veuillez voter pour que yield devienne réalité.

2
disfated

Oui et non.

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

Comme vous le voyez, vous pouvez implémenter quelque chose comme un en utilisant des fermetures, mais il n'a pas de générateurs natifs.

2
Not a Name

Mise à jour 2014: Node prend désormais en charge les rappels. Ce qui suit est un article de 2010.


Vous devez utiliser des rappels. Si la fonction fait quelque chose de manière asynchrone, vous pouvez également vouloir un rappel de continuation (la continuation est un mauvais mot, car cela signifie également autre chose, mais vous comprenez mon point.)

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...
})

Mis à jour avec un exemple de code

Je l'ai retourné, de sorte qu'il retourne true à la fin (puisque null, false et undefined sont tous évalués à false de toute façon).

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

Nous utilisons gnode pour les générateurs dans le nœud <0.11.3 - https://github.com/TooTallNate/gnode

0
manojlds

Oui Node.js et JavaScript ont maintenant à la fois des itérateurs synchrones (à partir d'au moins Node v6) et des itérateurs asynchrones (à partir de Node v10)):

Un exemple de générateur/itérateur avec sortie synchrone:

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

Un générateur/itérateur asynchrone similaire.

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

Il y a beaucoup à explorer, voici quelques bons liens. Je mettrai probablement à jour cette réponse avec plus d'informations plus tard:

0
John