setTimeout(f, 0)的应用&利用Deferred实现队列运行

任务:从mongodb中导出csv数据,输出内容如下
userid username usergender points

points表:

{ "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.");
}

 

posted @ 2013-12-12 21:33  Arliang  阅读(626)  评论(0编辑  收藏  举报