简体   繁体   English

Javascript / Node.js异步循环

[英]Javascript/Node.js async loop

I'm having trouble with the async nature of node in general. 我通常在节点的异步特性方面遇到麻烦。 Can someone help me with this block of code. 有人可以帮我这个代码块。 For various reasons I can only insert 1 row at a time into the database I am working with. 由于各种原因,我一次只能将1行插入正在使用的数据库中。 And actually, it would be even better if I could add a short delay to only insert 1 row per second into the database. 实际上,如果我可以增加一个短暂的延迟,以便每秒仅向数据库中插入1行,那将更好。

Here is a short section of my js code. 这是我的js代码的一小部分。

console.log('*** Inserting Records ***')
insertPromises = []
_.each(dbRecords, function (item) {
    var insertItem = buildRecord(item)
    insertPromises.push(conn.create(insertItem))
})
Promise.all(insertPromises).then(function (res) {
    _.each(res, function (item) {
        if (!item.success) {
            console.log("### Error ### " + JSON.stringify(res[i].errors))
        }
    })
    console.log('*** Inserted ' + res.length + ' Contacts')
})

My main question is how can I force the loop to wait for the conn.create promise to resolve before continuing the loop? 我的主要问题是如何在继续循环之前强制循环等待conn.create承诺解析? And is there a way to slow the loop to 1 iteration per second? 有没有一种方法可以将循环速度降低到每秒1次迭代?

A simple solution would be to keep track of an "insert count", that is, the current number of successfully inserted records. 一个简单的解决方案是跟踪“插入计数”,即成功插入记录的当前数量。 This will be your array pointer. 这将是您的数组指针。 Use a method to create each, individual promise and increment your "insert count" by 1 on each successful response. 使用一种方法来创建每个单独的承诺,并对每个成功的响应将“插入计数”加1。

let insertCount = 0;

function insertNextRecord() {
    conn.create(buildRecord(dbRecords[insertCount]).then(function(res){
        insertCount += 1;
        insertNextRecord();
    }).catch(function() {
        console.log('Error while inserting record ' + insertCount);
    });
}

insertNextRecord(); 

This is not tested and I'm making several assumptions about the code you're not showing. 这未经测试,我对您未显示的代码进行了一些假设。

This example assumes: 本示例假定:

  • dbRecords is an array dbRecords是一个数组
  • conn.create returns a promise object conn.create返回一个conn.create对象

To explicitly add a delay, you could use a timeout within the then method like so: 要显式添加延迟,可以在then方法中使用超时,如下所示:

let insertCount = 0;

function insertNextRecord() {
    conn.create(buildRecord(dbRecords[insertCount]).then(function(res){
        insertCount += 1;
        setTimeout(function() {
            insertNextRecord();
        }, 500);
    }).catch(function() {
        console.log('Error while inserting record ' + insertCount);
    });
}

insertNextRecord(); 

I should also say it's unfortunate that you have to do it this way. 我还应该说不幸的是您必须这样做。 This will be very slow when dealing with many inserts. 当处理许多插入时,这将非常慢。

Instead of using the recursion code posted above, you could check the async/await model. 除了使用上面发布的递归代码外,您还可以检查异步/等待模型。

An example of using this would be: 使用此示例:

async function processRecords(dbRecords) {

    for (let item of dbRecords) {
        try {
            let insertItem = buildRecord(item)
            await conn.create(insertItem)
            await delay(1000)
        } catch (e) {
           //handle error...
        }
   }

}

function delay(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms))
}

processRecords(dbRecords)

This is es7 code and you need babel compiler to transform it. 这是es7代码,您需要babel编译器对其进行转换。

It is probably better to use something like this if you find hard to keep up with promises and you want to stick with sync-like code. 如果您发现难以遵守承诺,并且希望坚持使用类似同步的代码,则最好使用这样的方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM