web-dev-qa-db-fra.com

Itérer sur les clés d'objet dans node.js

Depuis Javascript 1.7, il existe un Iterator object, qui permet ceci:

var a={a:1,b:2,c:3};
var it=Iterator(a);

function iterate(){
    try {  
        console.log(it.next());
        setTimeout(iterate,1000);
    }catch (err if err instanceof StopIteration) {  
        console.log("End of record.\n");  
    } catch (err) {  
        console.log("Unknown error: " + err.description + "\n");  
    }  

}
iterate();

y a-t-il quelque chose comme ceci dans node.js?

En ce moment j'utilise:

function Iterator(o){
    /*var k=[];
    for(var i in o){
        k.Push(i);
    }*/
    var k=Object.keys(o);
    return {
        next:function(){
            return k.shift();
        }
    };
}

mais cela produit beaucoup de surcharge en stockant toutes les clés d'objet dans k.

120
stewe

Ce que vous voulez, c'est une itération paresseuse sur un objet ou un tableau. Ceci n'est pas possible dans ES5 (donc pas possible dans node.js). Nous aurons cela éventuellement.

La seule solution est de trouver un module de noeud qui étend la V8 pour implémenter des itérateurs (et probablement des générateurs). Je n'ai trouvé aucune implémentation. Vous pouvez consulter le code source de spidermonkey et essayer de l'écrire en C++ en tant qu'extension V8.

Vous pouvez essayer ce qui suit, mais toutes les clés seront également chargées en mémoire.

Object.keys(o).forEach(function(key) {
  var val = o[key];
  logic();
});

Cependant, étant donné que Object.keys est une méthode native, cela peut permettre une meilleure optimisation.

Référence

Comme vous pouvez le constater, Object.keys est nettement plus rapide. Que le stockage réel de la mémoire soit plus optimal est une question différente.

var async = {};
async.forEach = function(o, cb) {
  var counter = 0,
    keys = Object.keys(o),
    len = keys.length;
  var next = function() {
    if (counter < len) cb(o[keys[counter++]], next);
  };
  next();
};

async.forEach(obj, function(val, next) {
  // do things
  setTimeout(next, 100);
});
214
Raynos

Rappelez-vous également que vous pouvez passer un deuxième argument à la fonction .forEach() en spécifiant l'objet à utiliser comme mot clé this.

// myOjbect is the object you want to iterate.
// Notice the second argument (secondArg) we passed to .forEach.
Object.keys(myObject).forEach(function(element, key, _array) {
  // element is the name of the key.
  // key is just a numerical value for the array
  // _array is the array of all the keys

  // this keyword = secondArg
  this.foo;
  this.bar();
}, secondArg);
21
amateur barista

Je suis nouveau sur node.js (environ 2 semaines), mais je viens de créer un module qui rapporte de manière récursive à la console le contenu d'un objet. Il listera tout ou recherchera un article spécifique, puis explorera une profondeur donnée si nécessaire.

Peut-être que vous pouvez personnaliser cela pour répondre à vos besoins. Rester simple! Pourquoi se compliquer? ...

'use strict';

//console.log("START: AFutils");

// Recusive console output report of an Object
// Use this as AFutils.reportObject(req, "", 1, 3); // To list all items in req object by 3 levels
// Use this as AFutils.reportObject(req, "headers", 1, 10); // To find "headers" item and then list by 10 levels
// yes, I'm OLD School!  I like to see the scope start AND end!!!  :-P
exports.reportObject = function(obj, key, level, deep) 
{
    if (!obj)
    { 
        return;
    }

    var nextLevel = level + 1;

    var keys, typer, prop;
    if(key != "")
    {   // requested field
        keys = key.split(']').join('').split('[');
    }
    else
    {   // do for all
        keys = Object.keys(obj);
    }
    var len = keys.length;
    var add = "";
    for(var j = 1; j < level; j++)
    {
        // I would normally do {add = add.substr(0, level)} of a precreated multi-tab [add] string here, but Sublime keeps replacing with spaces, even with the ["translate_tabs_to_spaces": false] setting!!! (angry)
        add += "\t";
    }

    for (var i = 0; i < len; i++) 
    {
        prop = obj[keys[i]];
        if(!prop)
        {
            // Don't show / waste of space in console window...
            //console.log(add + level + ": UNDEFINED [" + keys[i] + "]");
        }
        else
        {
            typer = typeof(prop);
            if(typer == "function")
            {
                // Don't bother showing fundtion code...
                console.log(add + level + ": [" + keys[i] + "] = {" + typer + "}");
            }
            else
            if(typer == "object")
            {
                console.log(add + level + ": [" + keys[i] + "] = {" + typer + "}");
                if(nextLevel <= deep)
                {
                    // drop the key search mechanism if first level item has been found...
                    this.reportObject(prop, "", nextLevel, deep); // Recurse into
                }
            }
            else
            {
                // Basic report
                console.log(add + level + ": [" + keys[i] + "] = {" + typer + "} = " + prop + ".");
            }
        }
    }
    return ;
};

//console.log("END: AFutils");
1

Pour une simple itération des clés/valeurs, des bibliothèques telles que underscorejs peuvent être vos amis.

const _ = require('underscore');

_.each(a, function (value, key) {
    // handle
});

juste pour référence

1
H6.

ajuster son code:

Object.prototype.each = function(iterateFunc) {
        var counter = 0,
keys = Object.keys(this),
currentKey,
len = keys.length;
        var that = this;
        var next = function() {

            if (counter < len) {
                currentKey = keys[counter++];
                iterateFunc(currentKey, that[currentKey]);

                next();
            } else {
                that = counter = keys = currentKey = len = next = undefined;
            }
        };
        next();
    };

    ({ property1: 'sdsfs', property2: 'chat' }).each(function(key, val) {
        // do things
        console.log(key);
    });
0
Lindy