你如何执行一个函数后,所有的承诺都解决了,你必须等待在循环内循环的异步调用?
代码被简化到最小
$scope.book = function(input) {
//Get the cart items from DB
ref.child('/cart/' + userId).once('value').then(function(cartSnap) {
//Loop through the cart items
cartSnap.forEach(function(cartItemSnap) {
var itemId = cartItemSnap.key();
//Get the inventory items from DB that are in the cart
ref.child('/inventory/' + itemId).once('value').then(function(inventoryItem) {
//Loop through booking IDs of inventoryItem
inventoryItem.child('rentals').forEach(function(rentalSnap) {
var rentalId = rentalSnap.key();
//Get bookings from rental/active
ref.child('/rental/'+ rentalId).once('value').then(function(activeRentals) {
checkIfBookingIsAllowed();
});
});
});
});
//Once everything was checked
bookRental();
});
};
为了提高速度,所有的请求都可以并行进行,但是最后的函数bookRental()只能在所有请求都解决后调用。
谢谢你的帮助。
编辑:又一次尝试失败了。Promise.all('collector')在所有承诺被解析之前被触发。所以'done'会在控制台的所有' checking '之前出现。
$scope.book = function(input) {
//Get the cart items from DB
ref.child('/cart/' + userId).once('value').then(function(cartSnap) {
//Promise collector
var collector = [];
//Loop through the cart items
cartSnap.forEach(function(cartItemSnap) {
var itemId = cartItemSnap.key();
//Get the inventory items from DB that are in the cart
var promise1 = ref.child('/inventory/' + itemId).once('value').then(function(inventoryItem) {
//Loop through booking IDs of inventoryItem
inventoryItem.child('rentals').forEach(function(rentalSnap) {
var rentalId = rentalSnap.key();
//Get bookings from rental/active
var promise2 = ref.child('/rental/'+ rentalId).once('value').then(function(activeRentals) {
console.log('check');
collector.push(promise2);
});
});
collector.push(promise1);
});
});
//Once everything was checked
Promise.all(collector).then(function() {
console.log('Done');
});
});
};
你收回承诺太晚了。现在就收集,而不是以后。.then
s中的代码稍后运行。
下面是立即运行的代码:
- 两个嵌套的for循环运行到完成,减去
.then
s内的所有代码。 -
Promise.all(collector)
.
此时collector
仍然是空的,因此Promise.all()
完成得非常快。
将collector.push(promise)
调用移出.then
调用。
更实用的方法:
有了上面的修复,你的代码应该可以工作了,但是更简洁的方法是返回所有的承诺。虽然forEach
不允许返回值,但map
允许,因此可以重写为(简化):
Promise.all(cartSnap.map(snap => ref.child(itemUrl).once('value').then(item =>
Promise.all(item.child('rentals').map(snap => ref.child(url).once('value'))))))
.then(allActiveRentals => console.log('Done'));