简体   繁体   English

从可观察到的返回数据的Angular forEach循环(Firebase驱动)

[英]Angular forEach Loop on returned data from observable (Firebase driven)

I have an observable from a service that returns an array of Payment objects, once I subscribe to my observable I perform a loop to add the amounts of each of the objects in the array. 我有一个可观察到的服务,该服务返回了一系列Payment对象,一旦我订阅了我的可观察对象,便执行循环以添加该数组中每个对象的数量。 the problem I'm having that on the first load the loop is not being executed for what I assume is because the data has not yet arrived, however, if I trigger .next on the subject of the observable it workes fine. 我遇到的问题是,在第一次加载时,由于我认为是因为数据尚未到达,所以尚未执行循环,但是,如果我在可观察的主题上触发.next,它可以正常工作。

The function of my component is like so: 我组件的功能如下:

paymentsSource = new Subject;
payments$ = this.paymentsSource.asObservable();
paymetsData:Payment[] = new Array();
totalPaymentsAmoutn:number = 0;

ngOnInit() {
  this.payments$
    .subscribe(
     (dates:{startDate:number, endDate:number}) => {
     //Here I need to performe some UTC and Locale conversion to dates thet are being passed on          
      };
      //Here I subscribe to my service          
      this.paymentService.getPaymentsByDateRange(dates.startDate, dates.endDate)
       .subscribe(
         payments => {
          this.totalPaymentsAmoutn = 0;
          this.paymetsData = payments;
          this.paymetsData.forEach( payment => {
            this.totalPaymentsAmoutn += payment.amount;
           })
          });      
       });


//this.paymentsStartDate is declear some where else but it does exist previous to this point
this.paymentsSource.next({startDate:this.paymentsStartDate, endDate:this.paymentsStartDate});

}

//This function I can triger manualy on the view
onPaymentDateRangeChanged($event){
  this.paymentsSource.next({startDate:$event.startDate, endDate:$event.endDate});
}

My Service function looks like this: 我的服务功能如下所示:

  getPaymentsByDateRange(startDate:number, endDate:number):Observable<Payment[]>{
    let paymentsArray:Payment[] = [];
    this.af.list('/bookings')
      .subscribe(
        (bookings) => {
          for(let booking of bookings){
            if(booking.payments){
              for(let payment of booking.payments){
                //condition for date range
                if(startDate <= payment.date && payment.date <= endDate){
                  payment.booking_key = booking.$key; 
                  paymentsArray.push(payment);
                }
              }
            }
          }
          //Sorting payments cronologicaly
          paymentsArray.sort(function(paymentA, paymentB){
            return paymentA.date - paymentB.date
          });
        }
      );
    return Observable.of(paymentsArray);
  }

When the page loads I do get the array back and the view gets populated but the value for this.totalPaymentsAmoutn remains 0, if I trigger the function manually it returns the array and updates the this.totalPaymentsAmoutn perfectly. 当页面加载时,我确实获取了数组并填充了视图,但是this.totalPaymentsAmoutn的值保持为0,如果我手动触发该函数,它将返回数组并完美地更新this.totalPaymentsAmoutn。

I am a bit new with Observables and I thought that once I subscribe to it if new data gets emitted It should run the script and update the data, I don't understand why on the first load is not working. 我对Observables有点陌生,我认为一旦发出新数据,我就订阅它,它应该运行脚本并更新数据,但我不明白为什么第一次加载无法正常工作。 I really think it has to do with not being able to perform the forEach loop since the array is still empty and I think that once the web sockets get connected consequent updates get push fast enough? 我真的认为这与无法执行forEach循环有关,因为该数组仍然为空,并且我认为一旦Web套接字建立连接,后续更新就会被足够快地推送吗?

There is a disconnect in your getPaymentsByDateRange() method. 您的getPaymentsByDateRange()方法中存在断开连接。 You are returning the paymentsArray before it is populated. 您将在填充之前返回paymentsArray。

getPaymentsByDateRange(startDate: number, endDate: number): Observable<Payment[]>{
    let paymentsArray: Payment[] = [];
    this.af.list('/bookings')
        .subscribe(...); // asynchronous
    // since this.af.list.subscribe is asynchronous, this returns before that call is finished.
    return Observable.of(paymentsArray);
}

You should instead return the af.list observable and subscribe only in the component. 相反,您应该返回可观察到的af.list并仅在组件中进行订阅。 If you need to preprocess the data before the component uses it, you can use the rxjs .map operator 如果需要在组件使用数据之前对其进行预处理,则可以使用rxjs .map运算符

import 'rxjs/add/operator/map'; // import map operator

getPaymentsByDateRange(startDate: number, endDate: number): Observable<Payment[]>{
    let paymentsArray: Payment[] = []; // you may want to move this inside the map. If you don't you may get duplicates everytime firebase emits the bookings
    return this.af.list('/bookings')
        .map(bookings => {
            for(let booking of bookings){
                if(booking.payments){
                    for(let payment of booking.payments){
                        //condition for date range
                        if(startDate <= payment.date && payment.date <= endDate){
                            payment.booking_key = booking.$key; 
                            paymentsArray.push(payment);
                        }
                    }
                }
            }
            //Sorting payments cronologicaly
            paymentsArray.sort(function(paymentA, paymentB){
                return paymentA.date - paymentB.date
            });
            return paymentsArray;
        });
}

This ensures that when you subscribe to this method, the onNext callback will only fire once the af.list observable emits. 这样可以确保在您订阅此方法时,仅在af.list observable发出后才触发onNext回调。

 this.paymentService.getPaymentsByDateRange(dates.startDate, dates.endDate)
     .subscribe(payments => {
         // fires when af.list observable emits
     });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 输入从Angular 2中的Observable返回的数据 - Inputting data returned from an Observable in Angular 2 如何枚举Angular 2中从Observable Subscription返回的数据? - How to enumerate data returned from Observable Subscription in Angular 2? 使用可观察到的Angular 2 / RxJs 5 beta从while循环流式传输数据 - Using Angular 2/RxJs 5 beta observable to stream data from a while loop 获取Observable返回的值 <any> 在Angular Typescript(Firebase)中 - Get value returned on Observable <any> in Angular Typescript (Firebase) Angular5:需要阻止 ngbTooltip 在从可观察的数据返回之前呈现 - Angular5: Need to prevent ngbTooltip from rendering before data is returned from observable 访问从HTTP Observable返回的数据 - Accessing data returned from HTTP Observable 从可观察对象返回的复杂对象访问数据 - Accessing data from a complex object that is returned by an observable 如何从Angular中的foreach循环返回数组数据 - How do I return array data from a foreach loop in Angular 如何从Firebase可观察对象返回转换后的对象,而其中的嵌套值必须从另一个Firebase可观察对象返回? - How to return a transformed object from a Firebase observable, where a nested value must be returned from another Firebase observable? Angular Firebase-从参考字段中可观察到 - Angular Firebase - Get observable from reference field
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM