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
相同。
我有一个包含 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
相同。