zoukankan      html  css  js  c++  java
  • 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.");
    }
  • 相关阅读:
    a和b互换的2种方式
    spring cloud 方法调用 feign
    spring boot redis 五种类型使用实例
    springboot引入properties文件 yml文件
    Spark-Streaming结合Redis
    Spark-Streaming结合Mysql案例
    Springboot与scala编写第一个web程序
    Springboot工程Mybatis二级缓存配置
    小奇画画
    saf
  • 原文地址:https://www.cnblogs.com/arliang/p/Deferred_queue_task.html
Copyright © 2011-2022 走看看