有一个for循环,在for循环内我调用了一个AJAX请求。我遇到的问题是,for循环在请求完成之前完成。
我希望for循环只有在所需的AJAX请求完成后才能继续进行下一次迭代。
PS-AJAX工作正常。我从服务器上获得了所需的信息。只需先完成for循环迭代,而无需等待AJAX请求成功函数启动。因此,当AJAX成功函数最终触发变量cid中的值时,由于它已被for循环的最后一次迭代覆盖,因此尚无定论。
我希望只有在执行AJAX成功函数后才能继续执行for循环。
代码:
if (window.cordova) {
db = $cordovaSQLite.openDB("my.db"); //device
} else {
db = window.openDatabase("my.db", '1', 'my', 1024 * 1024 * 100); // browser
}
var query = "SELECT * FROM order_product";
$cordovaSQLite.execute(db, query, []).then(function(res) {
if (res.rows.length > 0) {
for (var i = 0; i < res.rows.length; i++) {
console.log(" foreach SELECTED shopcart-> " + res.rows.item(i).id);
var cid = res.rows.item(i).coffee_id;
$http.post("http://192.168.1.4/coffeepayWeb/public/index.php/getsugar", {
cid: cID
})
.success(function(result) {
console.log("success");
if (cid == 6) {
//do something
} else {
//do something else
}
});
}
}
}
答案 0 :(得分:3)
如果需要迭代索引,使用for
对于异步操作是不安全的,只使用它来存储所需的值以进行异步操作(在这种情况下为$http.post
),它应该如下所示:
var items = [];
for (var i = 0; i < res.rows.length; i++) {
var item = res.rows.item(i);
items.push(item);
}
在考虑$http
返回承诺后,您应该能够映射items
var getsugarUrl = 'http://192.168.1.4/coffeepayWeb/public/index.php/getsugar';
// Map the values to obtain the promises on each $http operation, the allSettled method of the
// [Kriskowal Q library](https://github.com/kriskowal/q/wiki/API-Reference) will be simulated
// this is because when one of the http requests fail then the $q.all method break and reject with an error
var promises = items.map(function (item) {
var cid = item.coffee_id;
return $http.post(getsugarUrl, { cid: cid })
.then(function (result) {
// You can take advantage of this closure to handle the result of the request an the
// cid property, store your modified result on the value property from the return
return {
state: 'fullfilled',
value: {
result: result,
cid: cid
} // your modified result
};
})
// Handle when the http request fails
.catch(function (err) {
return {
state: 'rejected',
error: err
};
});
});
最后处理使用$ q.all获得的结果(您需要注入$ q服务)
$q.all(promises)
.then(function (responses) {
// iterate over the results
responses
.filter(function(response) { // only fullfilled results
return response.state == 'fullfilled';
})
.forEach(function (response) {
if (response.value.cid == 6) {
//do something with response.value.result
} else {
//do something else
}
});
});
使用此解决方案,http请求无法按顺序解析,但您可以控制它们何时完成并且您将具有正确的值cid
查看有关JavaScript Promises的更多信息
答案 1 :(得分:1)
$http
使用promises,这意味着您需要在承诺范例中考虑问题。
考虑一个递归选项,您传入一个cID数组,每个调用都会为数组中的第一个cID发送$http.post
;如果调用成功,我们将继续递归使用较小的数组,直到不再剩下。
创造了一个承诺&amp;在第一次调用中返回,每次成功查询都会收到通知(允许您执行per-cID逻辑),最后在所有查询完成时解析(或者在任何查询失败时被拒绝)。
// This function is called without deferred;
// deferred is used on recursive calls inside the function
function doPost(url, cidList, deferred) {
if (deferred === undefined) {
deferred = $q.defer();
}
var cid = cidList[0];
$http.post(url, {cid: cid})
.success(function(result) {
// query succeeded; notify the promise
deferred.notify({cid: cid, result: result});
if (cidList.length > 1) {
// there are more items to process; make a recursive
// call with cidList[1:end]
doPost(url, cidList.slice(1), deferred);
} else {
// we're done; resolve the promise
deferred.resolve();
}
})
.error(function(message) {
// there was an error; reject the promise
deferred.reject({cid: cid, message: message});
});
return deferred.promise;
}
// build the list of cIDs to pass into doPost
var cidList = [];
for (var i = 0; i < res.rows.length; i++) {
cidList.push(res.rows.item(i).coffee_id);
}
// start the queries
doPost("http://192.168.1.4/coffeepayWeb/public/index.php/getsugar", cidList)
.then(function() {
// promise resolved
console.log("All done!");
}, function(info) {
// promise rejected
console.log("Failed on cID " + info.cid + ": " + info.message);
}, function(info) {
// promise being notified
console.log("Just did cID " + info.cid + ": " + info.result);
// your per-cid handler
if (info.cid == 6) {
// do something
} else {
// do something else
}
});
由于问题的动机更多地与变量范围(而不是顺序HTTP请求)有关,这就是您真正需要的:
// Build the CID list so that we can iterate it
var cidList = [];
for (var i = 0; i < res.rows.length; i++) {
cidList.push(res.rows.item(i).coffee_id);
}
// Iterate the list & call $http.post
cidList.forEach(function(cid) {
// your $http.post() logic; each call will have its own
// cid thanks to closures
});
每次迭代都会拥有自己的cid
,您可以在.success()
或.error()
处理程序中使用它,而不必担心它会被覆盖。与其他解决方案一样,请求不是顺序的,但您可能并不需要它们在首位。