setTimeout(f, 0)的应用&利用Deferred实现队列运行
任务:从mongodb中导出csv数据,输出内容如下
userid username usergender pointspoints表:
{ "userid" : 1022, "points" : 12 }
//...上万条数据
{ "userid" : 2592, "points" : 4 }
{ "userid" : 7304, "points" : 44 }
{ "userid" : 7343, "points" : 40 }
{ "userid" : 7372, "points" : 12 }
{ "userid" : 7376, "points" : 4 }
{ "userid" : 7424, "points" : 20 }
{ "userid" : 7458, "points" : 4 }
{ "userid" : 7481, "points" : 24 }
{ "userid" : 7595, "points" : 4 }user表key
userid username usergender points
窃喜,很简单嘛,读取输出。
好,开干。
var points = [ //事先导出来了 { "userid" : 1022, "points" : 12 }, { "userid" : 2592, "points" : 4 }, { "userid" : 7304, "points" : 44 } ] var saveData = []; function readData(userid, callback){ db.collection('user').find({userid: userid}).toArray(function(error, data){ if(!error){ callback(data); } else { callback({}); } }); } function write(data){ //file writing... } var complete = 0; function run(){ for(var i = 0; i < points.length; i++){ readData(points, function(data){ saveData.push({ userid: data.userid, username: data.username, usergender: data.usergender, points: data.points }); complete++; if(complete == points.length){ write(data); } }); } } run();
结果可想而知,很多数据丢失,而且每次运行的结果都不一样——都是异步惹的祸,一拥而上,不死才怪
怎么让它一步步来呢?用Deferred写了个队列运行
function runQueueTasks(tasks){ var i = 0; function run() { if (!tasks[i]) { return; } when(Deferred(tasks[i])).then(function() { //run(); // May caught an RangeError: Maximum call stack size exceeded setTimeout(run, 0); // ←nextTick ↑recursion }); i++; } run(); }
搞定,收工。
其中有一句setTimeout(run, 0),我这里是为了避免递归溢出。
还有其它方面的资料可以自行搜索setTimeout 0,或参考setTimeout延时0毫秒的作用
可以试一下这两个函数:
function recursion(){ console.log("An RangeError will come very soon."); recursion(); console.log("You won't see me.") } // RangeError: Maximum call stack size exceeded function nextTick(){ console.log("Happy running."); setTimeout(nextTick, 0); console.log("The 2nd Happy running."); }
作者:阿良
出处:http://www.cnblogs.com/arliang
本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议
进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。