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

时间:2015-04-24 07:17:28

标签: javascript arrays callback pouchdb

我有一个数组,其中包含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") ;                                    
                       });

}

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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的用法相同。