繁体   English   中英

如何在 Observable 中避免 Observable

[英]How to avoid Observable inside Observable

我有一个带有 http 请求的服务,它返回我的标题的 Observables

服务.ts

get(sort: string): Observable<Response> {
    return this.http.get<any>(this.url, {...});
})

delete(id) {
  return this.http.delete(`${this.url}/${id}`, {...});
}

在我的组件中,我有一个 function 从服务获取请求中设置this.headlines 它看起来像这样:

interface IRes {
  searches: {
    label: string,
    id: number,
    value: string,
    ...
  }
}
headlines = [];

loadHeadlines() {
  this.service.get(data).subscribe((res: IRes) => this.headlines= res.headlines);
}

问题是有时我会收到带有空 label 的标题并且不需要显示它们,因此我需要对其进行过滤并发送.delete() 请求以获取此标题。 我试过这样的事情(想法是在订阅之前添加.pipe并在另一个subscribe中调用。)类似的东西

loadHeadlines() {
  this.service.get(data)
    .pipe(
      map(res: IRes => {
        res.headlines.filter(headline => !!headline.label.trim())
          .forEach(headline => this.service.delete(headline.id).subscribe())
      })
    )
    .subscribe((res: IRes) => this.headlines= res.headlines);
}

但不确定这是个好主意。 这里哪种方法更好?

您可以使用 RxJS switchMap运算符到 map 从一个可观察对象到另一个,然后forkJoin function 组合多个可观察对象。 我还使用了iif (with of ) function 来检查是否有要删除的空headline

但我不明白你目前使用的条件。 在 rest 上调用delete时,您似乎正在删除所有具有空label属性的headline元素。 所以本质上你是在所有有效元素上调用delete 也许它必须调整。

尝试以下

import { iif, forkJoin, of } from 'rxjs';
import { switchMap } from 'rxjs/operators';

loadHeadlines() {
  this.service.get(data).pipe(
    switchMap((res: IRes) => {
      const emptyHeadlines = res.headlines.filter(headline => !headline.label.trim()); // <-- all headlines with empty labels
      const deletes$ = forkJoin(
        emptyHeadlines.map(headline => this.service.delete(headline.id))
      ).pipe(
        map(_ =>  ({     // <-- map back to return only the headlines with defined `label`
          ...res,
          headlines: headlines.filter(headline => !!headline.label.trim())
        }))
      );
      return iif(
        () => !!emptyHeadlines.length,
        deletes$, // <-- execute delete only if there are empty headlines 
        of(res)   // <-- if not forward the response
      );
    })
  ).subscribe(
    (res: IRes) => this.headlines = res.headlines,
    (error: any) => console.log(error)
  );
}

好吧, ..headline.label.trim()绝对不是一个好主意,因为 double ! 将删除所有不为空的标题。 还有map应该是一个tap

所以对于完整的 pipe:

this.service.get(data).pipe(
    map(res => res.headlines)
    tap(headlines => headlines.filter(headline => !headline.label.trim()).forEach(
        headline => this.service.delete(headline.id)
    )),
    map(headlines => headlines.filter(headline => !!headline.label.trim())),
).subscribe(headlines => this.headlines= headlines);

在真实场景中,我将把它留给后端处理。 但是,这是强烈的观点,因为这里没有客观的对/错。

暂无
暂无

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

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