[英]Firebase (Angular) Promises with Loops in Loops
How do you execute a function only after all the promises are resolved where you have to wait for async calls in loops within loops? 仅在所有promise都解决之后,又如何在循环中等待异步调用的情况下,如何执行函数?
The code is simplified to the minimum 代码简化到最小
$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();
});
};
To improve speed all the requests can be made in parallel but the final function bookRental() can only be called when everything is resolved. 为了提高速度,可以并行执行所有请求,但是只有在解决所有问题后才能调用最终功能bookRental()。
Thanks for your help. 谢谢你的帮助。
EDITED: Another try that failed. 编辑:另一个尝试失败。 The Promise.all('collector') gets fired before all the promises are resolved.
Promise.all('collector')在所有诺言都解决之前就被解雇了。 So 'done' shows up before all the 'checks' in the console.
因此,在控制台中的所有“检查”之前都会显示“完成”。
$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');
});
});
};
You're collecting the promises too late. 您兑现承诺太迟了。 Collect them now , not later.
现在收集他们,而不是以后。 Code inside
.then
s runs later. .then
的代码稍后运行。
Here's what runs immediately: 这是立即运行的内容:
.then
s. .then
内的所有代码。 Promise.all(collector)
. Promise.all(collector)
。 At this point collector
is still empty, so Promise.all()
completes real fast. 此时
collector
仍为空,因此Promise.all()
快速完成。
Move the collector.push(promise)
calls outside of the .then
s. 将
collector.push(promise)
调用.then
之外。
With the above fix, your code should work, but a cleaner approach is to return all promises . 通过上述修复,您的代码应该可以运行,但是更干净的方法是返回所有promise 。 While
forEach
doesn't allow return values, map
does, so this can be re-written as (simplifying): 尽管
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'));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.