JS等待回调在for循环内完成执行

JS wait for callback to complete execution inside a for loop

我有一个包含 3 个数据的数组,我需要将其插入 pouchdb,所以我使用 for loop 来插入数据,但问题是它不是插入完整数据,因为循环在回调之前完成。

for(var i=0;i<data.length;i++){
   var jsondoc=doc1;//document
    console.log(i)  //getting console for all data. eg:1,2,3
    console.log(data[i])//getting console for all data. eg:hi, hello

    jsondoc.messages.push({msg: data[i]});   //updating message, here need to be done somthing           
                      db.put(jsondoc, function(err2, response2){
                         if (err2) { console.log(JSON.stringify(err2)); }
                            console.log("this is not repeating") ;                                    
                       });

}

如果我没理解错的话,你的问题是范围界定问题。 jsondoc 或 data[i],或导致问题的任何变量,在您的回调完成之前已更改。

看看这个 jsFiddle,它展示了如何解决此类范围界定问题。

for(var i = 0; i < 3; i++){
    (function(){
        var j = i;
        setTimeout(function(){
            callback(j)
        }, 500);
    })();
}

如果在 jsFiddle 运行时查看 js 控制台,您会看到第一个循环打印 3 次 3,这是 i 的最终值。而第二个,我们将值存储到新范围内的新变量,按预期输出 1、2、3。

由于 db insertion 运行异步,您不能暂停循环直到操作完成。您可以做的一件事是使用这样的辅助函数序列化 db inserts

function insertItem(data, i, completeCallback) {
    // check if we still have items to send
    if(i < data.length) {
        var jsondoc=doc1;//document
        //updating message, here need to be done somthing
        jsondoc.messages.push({msg: data[i]});   
        db.put(jsondoc, function(err2, response2){
            if (err2) { 
                console.log(JSON.stringify(err2)); 
            } 
            // recursively call to push the next message
            insertItem(data, i+1, completeCallback);
        });
    } else {
        // no more items to send, execute the callback
        if(typeof completeCallback === "function") {
            completeCallback();
        }
    }
}

您必须更新您的代码,以便在函数调用后不再继续执行,而是将该代码传递到 pushMessage 函数的回调中,因此如果您的原始代码看起来像这个:

// ... code before the loop
for(var i=0;i<data.length;i++){
    // ... original body of the loop
}
// ... code to execute after the loop and that currently causes problems

您需要像这样更改它:

// ... original code that was before the loop
insertItem(data, 0, function() {
    // ... original code hat was executed after the loop and that caused problems
    // but now it gets executed after all items were inserted in db
}

另一种选择是并行发送所有插入并对这些操作执行 join();不过,您仍然需要回调解决方法。沿线的东西:

function insertItems(data, callback) {
    var remainingItems = data.length;
    if(remainingItems === 0 && typeof callback === "function") {
        callback();
    }         
    for(var i=0;i<data.length;i++){
        var jsondoc=doc1;//document
        console.log(i)  //getting console for all data. eg:1,2,3
        console.log(data[i])//getting console for all data. eg:hi, hello

        jsondoc.messages.push({msg: data[i]});   //updating message, here need to be done somthing           
        db.put(jsondoc, function(err2, response2){
            if (err2) { console.log(JSON.stringify(err2)); }
            remainingItems--;
            if(remainingItems === 0 && typeof callback === "function") {
                // I know, code redundancy :P
                callback();
            }                                     
        });

    }
}

第二个函数的用法与insertItem相同。