【问题标题】:How to delay in node.js an operation in callback如何在node.js中延迟回调中的操作
【发布时间】:2016-05-20 13:34:49
【问题描述】:

我尝试将许多记录从 Firebird 复制到 MongoDB。这是我的功能;

var queue = 0;
connection.sequentially(sql, (row) => {
    queue++;
    collection.insert(row, (err, result) => {
        if (err)
            return done(err);
        queue--;
        if (queue <= 0)
          return done(null, result);
    });
}, (err) => {
    connection.detach();
    done(err);
}

我的问题是记忆力。写入操作较慢,大约 100000 次读取后我的内存已满。是否可以延迟下一次读取,直到队列的值下降到某个级别以下?

【问题讨论】:

    标签: javascript node.js mongodb asynchronous delay


    【解决方案1】:

    这是可以帮助您的众多解决方案之一,使用async.cargo,演示应该说明工作流程

    // npm install async --save
    var async = require('async');
    
    // your sql api, simple demo
    var collection = {
        insert: function (row, cb) {
            console.log('row inserted', row.name);
            cb(null);
        }
    };
    
    // create a cargo object with 1 row payload
    // and extract cargo into worker variable
    var cargo = async.cargo(function (cargo_rows, callback) {
        cargo_rows.forEach(function (row) {
            console.log('processing: ' + row.name);
            collection.insert(row, function(ciErr) {
                if(ciErr){
                    callback(ciErr);
                }
            }); // add rows, probably need some error checks
        });
        callback();
    }, 1); // number of cargo rows to process, if 2 - 2 rows will be inserted before callback called
    
    // add some items
    var rows = [{ name: 'item1' }, { name: 'item2' }, { name: 'item3' }];
    rows.forEach(function (row) {
        cargo.push(row, function (err) {
            if (err) {
                console.log('error processing: ' + row.name, '\nExiting');
            } else {
                console.log('finished processing: ' + row.name);
            }
        });
    });
    
    // Result
    // 
    // processing: item1
    // row inserted item1
    // finished processing: item1
    // processing: item2
    // row inserted item2
    // finished processing: item2
    // processing: item3
    // row inserted item3
    // finished processing: item3
    

    而当cargo_rows 的数量为2 时,结果为:

    // processing: item1
    // row inserted item1
    // processing: item2
    // row inserted item2
    // finished processing: item1
    // finished processing: item2
    // processing: item3
    // row inserted item3
    // finished processing: item3
    

    所以想法是顺序添加行,你的队列不是一个好的解决方案,你最好依赖promise,简单地说:

    start processing row =>  // you can have some validations here
    process row =>           // some error checking/logging
    finish process row =>    // cleanup memory, indeed i don't think you gonna need it
    have other rows ? restart worker with new row : done;
    

    【讨论】:

    • 一个问题:我已经尝试了 100000 条记录和 10000 的货物有效载荷。我可以看到所有记录都已处理,但 nodejs 脚本永远不会结束。我认为货物在等待新记录,但我没有。我可以在哪里以及如何销毁货物?
    • 您需要在货物内部致电callback。玩它,基本上应该在行插入完成时调用回调,而不是在外面,就像在我的演示中callback();
    猜你喜欢
    • 1970-01-01
    • 2016-04-04
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-23
    • 2014-01-15
    相关资源
    最近更新 更多