繁体   English   中英

Angular Observable 异步管道?

[英]Angular Observable async pipe?

考虑我有一个Rest API列出事件。

  • POST [203]:给出一系列事件。
  • POST [404]:未找到数据。

在这里,我的代码。

export function httpFetchRetry<T>(source: Observable<T>): Observable<T> {
  let errorScanner = (errorCount: number, error: any) => {
    if (errorCount >= 5) throw error;
    else if (error.status === 404) throw error;
    else return errorCount + 1;
  };
    
  return source.pipe(retryWhen(e => {
    return e.pipe(scan(errorScanner, 0), delay(3000))
  }));
}
    
export function httpFetchMap<T>(source: Observable<T>): Observable<T[]>{
  return source.pipe(map(({data}: any):any[] => data));
}

private listEvents(user_id: string){

  let url: string = `${environment.apiEndpoint}/event`;
  let payload: any = { user_id };

  this.allEvents$ = this.http.post(url, payload)
    .pipe(httpFetchRetry)
    .pipe(httpFetchMap)
}

该代码与async pipe一起工作得很好。

但是,现在我必须在UI上显示这些状态之一

<p> Loading </p>
<p> Loaded </p>
<p> No Data <p>
<p> Error <p>

Q1:如果我使用n 个异步管道,则会启动n 个API 调用。 我如何避免这种情况?

Q2:我如何获得这些状态之一


目前,我正在解决这个问题

.toPromise()
  .then(data => {
    this.data= data;
    this.noDataFound = false;
  })
  .catch(err => {
    if(err.status === 404){
      this.noDataFound = true;
    }
    else {
      this.snackBar.open("Something went wrong. Please try again.", null , { duration: 2000 });
    }
  })
  .finally(() => { this.pageLoader = false });

Observables 与 Promises 的不同之处在于它们在subscribed之前什么都不做。 您可以将转换管道链接到 Observable,但原始Observer函数将不会运行,直到包装它们的Observable被订阅。 它们与 Promise 的不同之处还在于 Observer 函数将为 Observable 的每个订阅运行。

http方法在它们完成之前返回一个冷的、有限的 Observable 和一个发射。 这里的 Observer 函数是 http 调用本身。 检查您的开发工具,您会发现在订阅 Observable 之前没有进行 http 调用。

async管道实际上在幕后subscribe Observable 并将其发射作为值展开,因此使用管道将导致 Observable 运行。 同样, toPromise操作符也订阅源Observable并将其转换为 Promise,因此它通过立即运行而表现得像 Promise。

async管道通常是解包Observable的推荐方式,但是对于像 http 请求这样的有限Observable ,您可能希望解包该值并将其保存在模板之外的某处:

private listEvents(user_id: string){
    
  let url: string = `${environment.apiEndpoint}/event`;
  let payload: any = { user_id };
    
  this.http.post(url, payload)
    .pipe(httpFetchRetry, httpFetchMap)
    .subscribe(s => this.allEvents = s);
}

一个好的设计模式是将这个值保存在一个服务中以供多个组件访问。

暂无
暂无

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM