Начиная с Javascript 1.7 существует объект Iterator , который позволяет это:
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();
есть ли что-то подобное в node.js?
Сейчас я использую:
function Iterator(o){
/*var k=[];
for(var i in o){
k.push(i);
}*/
var k=Object.keys(o);
return {
next:function(){
return k.shift();
}
};
}
но это приводит к большим накладным расходам из-за хранения всех ключей объекта k
.
javascript
node.js
iterator
Stewe
источник
источник
createNodeIterator
, для элементов DOM, у меня даже DOM нет;) @ c69: я храню все данные вkeys
объекте, иvalue
просто установлено значение1
(около 20 МБ в ключах 700k), действительно, для теперь я просто игнорирую эти «накладные расходы», но я бы предпочел лучшее решение :)Ответы:
Вам нужна ленивая итерация по объекту или массиву. Это невозможно в ES5 (следовательно, невозможно в node.js). В конце концов мы это получим.
Единственное решение - найти модуль узла, который расширяет V8 для реализации итераторов (и, возможно, генераторов). Я не нашел никакой реализации. Вы можете посмотреть исходный код spidermonkey и попробовать написать его на C ++ как расширение V8.
Вы можете попробовать следующее, но он также загрузит все ключи в память
Object.keys(o).forEach(function(key) { var val = o[key]; logic(); });
Однако, поскольку
Object.keys
это собственный метод, он может обеспечить лучшую оптимизацию.Контрольный показатель
Как видите, Object.keys значительно быстрее. Другой вопрос, будет ли фактическое хранилище памяти более оптимальным.
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); });
источник
forEach
так как каждый шаг итерации должен вызываться из асинхронногоsetTimeout
async.forEach
Также помните, что вы можете передать второй аргумент
.forEach()
функции, определяющей объект, который будет использоваться в качестве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);
источник
Object.keys(myObject).forEach(function(key, index, arrayOfKeys) {
Для простой итерации ключей / значений иногда вам могут помочь библиотеки, такие как underscorejs .
const _ = require('underscore'); _.each(a, function (value, key) { // handle });
просто для справки
источник
underscorejs
. Я использовал эту функцию изlodash
библиотеки.Я новичок в node.js (около 2 недель), но я только что создал модуль, который рекурсивно сообщает на консоль о содержимом объекта. Он будет перечислять все или искать конкретный элемент, а затем, при необходимости, углубляться на заданную глубину.
Возможно, вы сможете настроить это под свои нужды. Будь проще! Зачем усложнять? ...
'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");
источник
отрегулируйте его код:
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); });
источник