Angular Observable首先需要完成 [英] Angular Observable need to complete first

查看:197
本文介绍了Angular Observable首先需要完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

@Input() list: string[];

ngOnInit() : void {
   this.valueMap = new Map<any, any>();
   this.getDataFromService();
   this.buildContainer();
}

private getDataFromService(): void {
  this.list.forEach(value-> {
      this.fetchService(value).subscribe(data ->{
          this.valueMap.set(value,data);
          }
       )
   })
}

private buildContainer(): void {
   console.log(this.valueMap.size); // shows always 0 even when service returns the data 
 }

现在,我必须在方法buidlContainer()中使用此valueMap , 因此,我需要先从服务中获取完整的地图.当我在buildConatainer()中使用该映射时,它向我显示了undefined.

Now thing is that I have to use this valueMap in the method buidlContainer() , hence I need to get the complete map first from service. And when I use that map in buildConatainer() it shows me undefined .

我了解到这是一些异步调用问题.另外,我不能为.subscribe()中的每个值调用buildContainer()方法,因为这不是更好的主意. 因此,我必须先计算Map,然后再进行进一步处理.

I understood that this is some async call issue . Also , I can not call method buildContainer() for each value in .subscribe() as that would not be better idea. So , I have to compute the Map first before processing that further..

我们将不胜感激,并且我无法将服务从可观察的"返回承诺"返回

Any help is appreciated and i can not modify the service from returning Observable to return Promise

我要执行以下操作

private buildContainer(): void {
   for([key,data] of this.valueMap) {
      -----some code----
    }
 }

推荐答案

这是向代码中引入反应性范例的缺点之一(或优点取决于您的看法).反应过程的单点将逐渐或部分或完全爬入代码的其他部分.

This is one of the disadvantage (or advantage depending how you look at it) of introducing reactive paradigm to your code. A single point of reactive procedure would gradually creep into other parts of the code either partially or completely.

因此,我建议您也使valueMap具有反应性,并使其根据getDataFromService()服务中的更改做出响应.一种方法是将valueMap变量设置为RxJS ReplaySubject 带有1的缓冲区.因此它将缓冲(或保留)它的最后一个值,并在订阅后立即将其发出.

So I'd recommend you to make the valueMap reactive as well and make it respond based on the changes in getDataFromService() service. One way would to make the valueMap variable a RxJS ReplaySubject with a buffer of 1. So it'll buffer (or hold) it's last value pushed to it and emit it immediately upon subscription.

尝试以下

import { forkJoin, ReplaySubject, Subject } from 'rxjs';
import { take, takeUntil } from 'rxjs/operators';

valueMap: ReplaySubject<Map<any, any>> = ReplaySubject<Map<any, any>>(1);
completed$ = new Subject<any>();

@Input() list: string[];

ngOnInit(): void {
  this.valueMap = new Map <any, any>();
  this.getDataFromService();
  this.buildContainer();
}

private getDataFromService(): void {
  forkJoin(this.list.map(value => this.fetchService(value))).pipe(
    takeUntil(this.completed$)             // <-- close subscription upon component `ngOnDestroy` hook trigger
  ).subscribe(
    data => {
      let map = new Map<any, any>();
      data.forEach((item, i) => {
        map.set(this.list[i], item);
      });
      this.valueMap.next(map);
    }
  );
}

private buildContainer(): void {
  this.valueMap.asObservable().pipe(
    take(1)               // <-- emit only the first notification and complete
  ).subscribe(
    data => {
      console.log(this.valueMap.size);
    }
  );
}

ngOnDestroy() {
  this.completed$.next();
  this.completed$.complete();
}

我还使用了RxJS forkJoin() 函数结合多个可观察对象,并 takeUntil 运算符在销毁组件时关闭订阅

I've also used RxJS forkJoin() function to combine multiple observables and takeUntil operator close the subscription when the component is destroyed.

工作示例: Stackblitz

在示例中,我使用了 jsonplaceholder API在fetchService()功能.

In the example, I've used jsonplaceholder API to mock some HTTP calls in the fetchService() function.

注意:

  1. 仅当所有可观察物都完成时,forkJoin()才会发射.如果要处理数据流,则必须用 combineLatest zip

  1. The forkJoin() will emit only if all the observables complete. If you're dealing with a stream of data, you will have to replace it with either combineLatest or zip based on your requirement.

一个明显的问题是,如果快速连续多次调用buildContainer()函数,则每次都会触发单独的订阅.

There is an obvious issue where if the buildContainer() function is called multiple times in quick successions, each will trigger individual subscriptions.

这篇关于Angular Observable首先需要完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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