2011-12-27 50 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没有像Lua的next()功能,可以让你找到一个给定后的下一个键/值对。

如果您关心条目的顺序,那么您需要将原始键/值对存储在数组中,而不是对象。

+0

所以你必须创建一个数组来做到这一点?没有创建数组没有办法? – 2011-12-27 17:31:46

+0

@luxun - JS对象属性不是有序的。你可以只保留数组中的顺序(而不是数值)。在这种情况下,您将拥有两个数据结构,一个用于属性顺序的数组和一个用于保存属性值的对象。 – 2011-12-27 17:38:43

+0

@luxun如果你可以依赖迭代的顺序(一些浏览器保证),你可以通过存储最后一个键的可怕机制,然后(在每个回调中)遍历对象,直到你看到该键。但是,这不仅是可怕的低效率,它不保证按照规范工作。 – Phrogz 2011-12-27 17:48:59