2011-12-27 2 views
1

Учитывая этот код:Перебор объекта ключ/значения асинхронно

var o = { 
    k1: 'v1', 
    k2: 'v2', 
    k3: 'v3' 
}; 

var stupidf = function(k, v, callback) { 
    setTimeout(function() { 
    console.log(k + "=" + v); 
    callback(); 
    }, 2000}; 
}; 

Какой самый лучший способ произвести вывод:

// after 2 seconds 
stdout: k1=v1 
// after 4 seconds 
stdout: k2=v2 
// after 6 seconds 
stdout: k3=v3 

С массива, вы бы сделать копию и push() оно с обратными вызовами, но я не могу понять, как это сделать с объектом.

ответ

1

Вы предполагаете, что итерация записей в o имеет гарантированный заказ; it does not. Предполагая, что вы не все равно, что заказ вы получаете их:

function asyncIterate(o,callback,timeout){ 
    var kv=[], i=0; 
    for (var k in o) if (o.hasOwnProperty(k)) kv.push([k,o[k]); 
    var iterator = function(){ 
    callback(kv[i][0],kv[i][1]); 
    if (++i < kv.length) setTimeout(iterator,timeout); 
    } 
    setTimeout(iterator,timeout); 
} 
asyncIterate(o,function(k,v){ 
    console.log(k+'='+v); 
},2000); 

JavaScript не имеет что-то вроде next() функции Lua, что позволяет найти следующую пару ключ/значение после данной.

Если вы заботитесь о порядке записей, вам необходимо сохранить исходные пары ключ/значение в массиве, а не объекте.

+0

Итак, вам нужно создать массив, чтобы сделать это? Нет способа без создания массива? –

+0

@ luxun - свойства объекта JS НЕ заказываются. Вы можете сохранить только порядок (а не значения) в массиве. В этом случае у вас будут две структуры данных, массив для порядка свойств и объект для хранения значений свойств. –

+0

@ luxun Если вы можете положиться на порядок итераций (что гарантируют некоторые браузеры), вы можете сделать это через ужасный механизм хранения последнего увиденного ключа и затем (при каждом обратном вызове), итерации объекта до тех пор, пока вы не увидите этот ключ. Но это не только ужасно неэффективно, но и не гарантируется работа по спецификации. – Phrogz

Смежные вопросы