Firebase(角度)承诺在循环中循环 [英] Firebase (Angular) Promises with Loops in Loops

查看:46
本文介绍了Firebase(角度)承诺在循环中循环的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只有在所有promise都解决了之后,才能在循环内等待异步调用的情况下,如何执行功能?

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?

代码已简化到最小

$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()仅在所有问题解决后才能调用.

To improve speed all the requests can be made in parallel but the final function bookRental() can only be called when everything is resolved.

感谢您的帮助.

另一个尝试失败了.Promise.all('collector')在所有诺言被兑现之前就被解雇了.因此,在控制台中的所有检查"之前都会显示完成".

EDITED: Another try that failed. The Promise.all('collector') gets fired before all the promises are resolved. 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');
    });
  });
};

推荐答案

您收拾承诺的时间太晚了.立即收集它们,现在.中的代码.然后 s稍后运行.

You're collecting the promises too late. Collect them now, not later. Code inside .thens runs later.

这是立即运行的内容:

  1. 两个嵌套的for循环都运行完毕,减去 .then s中的所有代码.
  2. Promise.all(collector).
  1. Both nested for-loops run to completion, minus all code inside .thens.
  2. Promise.all(collector).

此时, collector 仍然为空,因此 Promise.all()可以快速完成.

At this point collector is still empty, so Promise.all() completes real fast.

collector.push(promise)调用移到之外.然后 s.

使用上述修复程序,您的代码应该可以工作,但是更干净的方法是退还所有诺言.尽管 forEach 不允许返回值,但 map 允许返回值,所以可以将其重写为(简化):

With the above fix, your code should work, but a cleaner approach is to return all promises. While forEach doesn't allow return values, map does, so this can be re-written as (simplifying):

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'));

这篇关于Firebase(角度)承诺在循环中循环的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆