【问题标题】:JS wait for callback to complete execution inside a for loopJS 在 for 循环中等待回调完成执行
【发布时间】:2015-07-02 16:17:09
【问题描述】:

我有一个包含 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") ;                                    
                       });

}

【问题讨论】:

  • 您是否有理由不希望 loop 在插入完成之前完成?
  • if (jsondoc.messages.length === data.length - 1) {db.put()} ?
  • 不,没有特别的理由使用 for 循环 @Cristik

标签: javascript arrays callback pouchdb


【解决方案1】:

由于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一样。

【讨论】:

    【解决方案2】:

    如果我对您的理解正确,您的问题是范围问题。 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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-27
      • 1970-01-01
      • 2014-07-19
      • 1970-01-01
      • 2020-04-01
      • 1970-01-01
      • 2015-09-10
      • 2021-02-15
      相关资源
      最近更新 更多