所以,我一直在考虑一个脑筋急转弯 - 如果我有一个大型对象,我出于某种原因必须在节点js中迭代,并且在我这样做时不想阻止事件循环怎么办?
这是一个非常头脑的例子,我相信它可以更清洁:
var forin = function(obj,callback){
var keys = Object.keys(obj),
index = 0,
interval = setInterval(function(){
if(index < keys.length){
callback(keys[index],obj[keys[index]],obj);
} else {
clearInterval(interval);
}
index ++;
},0);
}
虽然我确定它有其他原因让它变得混乱,但这会比常规for循环执行得慢,因为setInterval 0实际上并不是每0 ms执行一次,但我不知道如何制作循环使用更快的process.nextTick。
在我的测试中,我发现这个例子需要7毫秒才能运行,而不是原生的for循环(使用hasOwnProperty()检查,记录相同的信息),这需要4毫秒。
那么,使用node.js编写相同代码的最干净/最快的方法是什么?
答案 0 :(得分:3)
自提出问题以来process.nextTick
的行为发生了变化。以前的答案也没有按照功能的清洁度和效率来回答问题。
// in node 0.9.0, process.nextTick fired before IO events, but setImmediate did
// not yet exist. before 0.9.0, process.nextTick between IO events, and after
// 0.9.0 it fired before IO events. if setImmediate and process.nextTick are
// both missing fall back to the tick shim.
var tick =
(root.process && process.versions && process.versions.node === '0.9.0') ?
tickShim :
(root.setImmediate || (root.process && process.nextTick) || tickShim);
function tickShim(fn) {setTimeout(fn, 1);}
// executes the iter function for the first object key immediately, can be
// tweaked to instead defer immediately
function asyncForEach(object, iter) {
var keys = Object.keys(object), offset = 0;
(function next() {
// invoke the iterator function
iter.call(object, keys[offset], object[keys[offset]], object);
if (++offset < keys.length) {
tick(next);
}
})();
}
请注意@alessioalex's comments关于Kue和正确的工作排队。
另见:share-time,我写的一个模块,用来做与原问题相似的事情。
答案 1 :(得分:1)
这里有很多事情要说。
对于这些方法,您还可以使用多个进程(用于并发)。
现在是时候提供一个示例代码(可能不完美,所以如果你有更好的建议,请纠正我):
var forIn, obj;
// the "for in" loop
forIn = function(obj, callback){
var keys = Object.keys(obj);
(function iterate(keys) {
process.nextTick(function () {
callback(keys[0], obj[keys[0]]);
return ((keys = keys.slice(1)).length && iterate(keys));
});
})(keys);
};
// example usage of forIn
// console.log the key-val pair in the callback
function start_processing_the_big_object(my_object) {
forIn(my_object, function (key, val) { console.log("key: %s; val: %s;", key, val); });
}
// Let's simulate a big object here
// and call the function above once the object is created
obj = {};
(function test(obj, i) {
obj[i--] = "blah_blah_" + i;
if (!i) { start_processing_the_big_object(obj); }
return (i && process.nextTick(function() { test(obj, i); }));
})(obj, 30000);
答案 2 :(得分:1)
而不是:
for (var i=0; i<len; i++) {
doSomething(i);
}
做这样的事情:
var i = 0, limit;
while (i < len) {
limit = (i+100);
if (limit > len)
limit = len;
process.nextTick(function(){
for (; i<limit; i++) {
doSomething(i);
}
});
}
}
这将循环100次迭代,然后将控制权返回系统片刻,然后从中断处继续,直至完成。
编辑:这里它适用于您的特定情况(以及它作为参数传入时执行的迭代次数):
var forin = function(obj, callback, numPerChunk){
var keys = Object.keys(obj);
var len = keys.length;
var i = 0, limit;
while (i < len) {
limit = i + numPerChunk;
if (limit > len)
limit = len;
process.nextTick(function(){
for (; i<limit; i++) {
callback(keys[i], obj[keys[i]], obj);
}
});
}
}
答案 3 :(得分:-1)
以下适用于[浏览器] JavaScript;它可能与node.js完全无关。
我知道的两个选项:
我不确定Web Workers是否适用/可用。
快乐的编码。