【问题标题】:How to implement async pipe in angular httpclient?如何在角度 httpclient 中实现异步管道?
【发布时间】:2020-02-15 03:18:28
【问题描述】:

我试图根据将通过 HTTP get 调用检索的数据加载子组件。我正在使用服务来执行 HTTP 调用并订阅组件的构造函数。但是 ngif 在数据检索之前调用。

所以我在 ngif 中应用了异步管道,但它触发了另一个错误。

服务代码:

GetContest(id){
    return this.http.get(this.baseurl+id);
}

组件的构造函数:

this.service.GetContest(this.route.snapshot.paramMap.get('id')).
    subscribe( (res)=> {
      this.contest = res;
      console.log(this.contest);
    });

模板 ngif:

<app-beforecontest *ngIf="contest.startTime<date "></app- 
beforecontest>

以上代码产生错误:

TypeError: Cannot read property 'startTime' of null

在此之后我像这样加入了异步管道:

<app-beforecontest *ngIf="(contest|async).startTime<date "></app- 
beforecontest>

它正在生成错误:

ContestComponent.html:1 ERROR Error: InvalidPipeArgument: '[object 
Object]' for pipe 'AsyncPipe'
at invalidPipeArgumentError

【问题讨论】:

  • 异步管道在 observables 上工作,不清楚你为什么期望它会这样工作。

标签: angular async-await angular-httpclient angular-pipe


【解决方案1】:

你可以在你的component.ts中设置this.contest的初始值为null

this.contest = null

并在模板中像这样检查它:

<app-beforecontest *ngIf="contest?.startTime < date"></app- 
beforecontest>

@jonrsharpe 感谢您清除此问题

请注意,startTime&lt;date "&gt; 是一个非常奇怪的字符串,我不知道你的意思。

一般来说,如果你想使用异步管道,你应该在 Observable 上使用它:

myObservable$ = this.service.GetContest(this.route.snapshot.paramMap.get('id'));

如您所见,我们没有 .subscribe 处理它(!!!)

在模板中首先异步observable,然后添加.startTime

<app-beforecontest *ngIf="(myObservable$ | async).startTime < date"></app-beforecontest>

【讨论】:

  • "very wierd string" - 这是一个比较,是条件表达式的一部分,可能更清楚...startTime &lt; date"
【解决方案2】:

异步管道需要用于可观察对象,我创建了一个简单的 stackblitz 来展示它:https://stackblitz.com/edit/angular-tx7g36

您需要更改的主要代码在组件本身中

import { Component } from '@angular/core';
import {ContestService} from './contest.service';
import {Observable} from 'rxjs';

@Component({
  selector: 'my-app',
  template: `
    <h1>Contest startTime</h1>
    <p>{{(contest$ | async)?.startTime}}</p>
  `,
})
export class AppComponent  {
  contest$: Observable<any>;

  constructor(private contestService: ContestService) {
    this.contest$ = this.contestService.getContest();
  }
}

如果您对比赛属性末尾的 $ 感到疑惑,那是一种区分 observable 与其他类型数据的符号。

【讨论】:

    【解决方案3】:

    在处理异步响应和绑定模板的情况下,您可以像这样使用安全导航运算符 -

    <app-beforecontest *ngIf="contest?.startTime<date "></app- 
    beforecontest>
    

    否则,如果你想使用异步管道,你必须像下面的 mannet 一样使用它 -

    <app-beforecontest *ngIf="contest.startTime | async"></app-beforecontest>
    

    PS:但是在您的情况下,contest 本质上不是 asnyc,您只是将其分配给来自异步请求的值。所以最好使用安全导航算子?

    【讨论】:

    • 是的,它隐藏了错误,但模板 ngif 仍在检索 httpcall 之前检查数据。所以我的主要问题没有解决。
    • 您在控制台中对console.log(this.contest); 的响应是什么?
    • ideone.com/YpGPpX 在这里查看订阅的第一个控制台日志,比赛打印正确,但第二个控制台日志未定义
    • 因为您的方法异步返回结果,这就是没有定义第二个控制台的原因。只有当您的请求返回成功时,第一个控制台才会执行。
    • 但这并没有解决我的问题。那么解决办法是什么?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-19
    • 2019-04-10
    • 2021-02-02
    • 2016-09-05
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    相关资源
    最近更新 更多