JS waits for callback to complete inside for loop
I have an array of 3 data that I need to insert into pouchdb
, so I am using for loop
to insert data, but the problem is that this is not inserting full data, because the loop ends before the 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)); }
console.log("this is not repeating") ;
});
}
source to share
Since db insertion
async works, you cannot put the loop on hold until the operation completes. One thing you can do is serialize db inserts
with a helper function like this:
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 will need to update your code to pass that code to the function callback instead of continuing execution after the function call pushMessage
, so if your original code looks like this:
// ... 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 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 execute join()
for those operations; you still need a callback workaround. Something like 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 use of this second function is the same as for insertItem
.
source to share
If you understand correctly, your problem is related to the problem. jsondoc or data [i], or whichever variable is causing the problem, is changed before the callback completes.
Take a look at the jsFiddle which shows how to solve such a problem.
for(var i = 0; i < 3; i++){
(function(){
var j = i;
setTimeout(function(){
callback(j)
}, 500);
})();
}
If you look at the js console when running jsFiddle, you can see that the first loop prints 3 times 3, which is the finish value for i. Whereas the second, where we store the value for the new variable in the new scope, outputs 1, 2, 3 as expected.
source to share