【问题标题】:How to call function after observable is readyobservable 准备好后如何调用函数
【发布时间】:2021-04-06 23:39:58
【问题描述】:

我是 Angular 和 Observables 的新手。我的问题是: 在我的组件 HomePage 中,我调用了调用 http.get 并返回 observable 的服务。在我的模板主页上,我对此数据使用异步 $。我需要在 ngOnInit 中调用另一个 void 函数,该函数将在返回时使用 data$。所以我无法弄清楚如何做到这一点。

主页.ts

export class HomePage implements OnInit {

  data$: Observable<any>;

  ngOnInit(): void {
    //I need userId that will be returned here
    this.data$ = this.dataService.getMyData(); 
    //how to call this function after data$ is returned?
    this.sendMessage(data.userId);
  }

  sendMessage(data.userId){
     //send this userId 
  }
}

主页.html

<app-homepage form="true" *ngIf="{ data: data$ | async} as myData">
<div *ngIf="data.userId">
///....

我已经尝试过了:但是每次我在页面上输入一些数据时 - 它都会多次调用 sendMessage()...

this.data$ = this.dataService.getMyData().pipe(
      tap((data) => {
        this.sendMessage(data.userId);
        console.log("in pipe")//here I see multiple calls when I click on checkbox for exemple..
      }));

【问题讨论】:

    标签: angular angular2-observables


    【解决方案1】:

    试试

    this.data$ = this.dataService.getMyData().pipe(
      take(1),
      tap((data) => {
        this.sendMessage(data.userId);
        console.log("in pipe")//here I see multiple calls when I click on checkbox for exemple..  
      }
    ));
    

    【讨论】:

      【解决方案2】:

      如果您的服务返回 Observable,那么您需要向它发送 subscribe 以读取响应内容,如下所示:

      export class HomePage implements OnInit {
      
        // data$: Observable<any>;
        theResult: any;
      
        ngOnInit(): void {    
          this.dataService.getMyData().subscribe((response) => {
            console.log('See your response', response);
            theResult = response.userId;
            this.sendMessage(theResult);
          });
        }
      
        sendMessage(data.userId){
           //send this userId 
        }
      }
      

      请记住,当你 subscribe 到一个 Observable 时,这是一个 asynchronous 操作,这就是为什么在你在 subscribe 步骤中获得 response 之后,你需要调用你的另一个功能。

      【讨论】:

      • 我在模板中使用异步管道订阅,所以我不想再次订阅
      【解决方案3】:

      当通过流发出值时,使用 tap 运算符是运行副作用的适当方式。

      如果要防止多个订阅触发副作用逻辑,可以使用shareReplay操作符来防止这种行为:

      this.data$ = this.dataService.getMyData().pipe(
          tap(data => this.sendMessage(data.userId)),
          shareReplay()
      );
      

      这是StackBlitz 示例

      每次我在页面上输入一些数据 - 它都会多次调用 sendMessage()

      如果与页面的交互导致调用多次执行,则更改检测可能会以某种方式导致这种情况。您可能需要共享更多代码才能弄清楚为什么会这样。

      【讨论】:

      • 所以你说在这种情况下使用tap可以吗?而且我真的不明白“防止多次订阅”是什么意思?
      • 我认为是的,这是导致多次调用的“更改检测”。但这是正常的吗?即使我没有添加我的函数调用它也存在吗?我的意思是这个函数 -> .pipe(tap(data => this.sendMessage(data.userId))
      • 是的,tap 是执行副作用的合适运算符。来自文档:“tap - 对源 Observable 的每个发射执行副作用”。但是,这发生在每个订阅者身上。由于您只想在所有订阅中执行一次副作用,因此您可以根据非官方文档 "shareReplay - ...当您有副作用或计算不希望的繁重计算时使用 shareReplay在多个订阅者之间执行"
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-12-29
      • 2011-11-14
      • 1970-01-01
      • 2016-01-20
      • 1970-01-01
      • 1970-01-01
      • 2019-04-05
      相关资源
      最近更新 更多