简体   繁体   English

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

[英]JS wait for callback to complete execution inside a for loop

I am having an array which consist of 3 data which I need to insert in pouchdb , so I'm using a for loop to insert the data, but the problem is it is not inserting complete data because the loop finishes before callback. 我有一个数组,其中包含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") ;                                    
                       });

}

If I understand you correctly, your problem is a scoping issue. 如果我理解正确,那么您的问题就是一个范围问题。 jsondoc or data[i], or whichever variable is causing the problem, is changed before your callback can complete. jsondoc或data [i],或导致问题的变量,在回调完成之前更改。

Take a look at this jsFiddle , which shows how to solve such a scoping problem. 看看这个jsFiddle ,它展示了如何解决这样一个范围问题。

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

If you look at your js console when the jsFiddle runs you'll see that the first loop prints 3 times 3, which is the finishing value for i. 如果你在jsFiddle运行时查看你的js控制台,你会看到第一个循环打印3次3,这是i的结束值。 While the second, where we store the value to a new variable inside a new scope, outputs 1, 2, 3 as expected. 而第二个,我们将值存储到新范围内的新变量,按预期输出1,2,3。

Since the db insertion runs async, you cannot put the loop on hold until the operation completes. 由于db insertion运行异步,因此在操作完成之前无法将循环置于保持状态。 One thing that you can do is to serialise the db inserts with a helper function like this: 您可以做的一件事是使用这样的辅助函数序列化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();
        }
    }
}

You'll have to update your code so that instead of continuing the execution after the call of the function, to pass that code into the callback of the pushMessage function, so if your original code looks like this: 您必须更新代码,以便在调用函数后不再继续执行,将该代码传递给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

you'll need to change it like this: 你需要像这样改变它:

// ... 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
}

Another alternative would be to send all inserts in parallel and perform a join() on those operations; 另一种方法是并行发送所有插入并对这些操作执行join() ; you'll still need the callback workaround though. 你仍然需要回调解决方法。 Something along the lines: 一些事情:

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();
            }                                     
        });

    }
}

The usage of this second function is the same as for insertItem . 第二个函数的用法与insertItem的用法相同。

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

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