[英]How to avoid Observable inside Observable
I have a service with http request which return Observables of my Headlines我有一个带有 http 请求的服务,它返回我的标题的 Observables
servise.ts服务.ts
get(sort: string): Observable<Response> {
return this.http.get<any>(this.url, {...});
})
delete(id) {
return this.http.delete(`${this.url}/${id}`, {...});
}
and in my component I have a function that set this.headlines
from service get request.在我的组件中,我有一个 function 从服务获取请求中设置
this.headlines
。 It looks like this:它看起来像这样:
interface IRes {
searches: {
label: string,
id: number,
value: string,
...
}
}
headlines = [];
loadHeadlines() {
this.service.get(data).subscribe((res: IRes) => this.headlines= res.headlines);
}
The problem is that sometimes I receive headline with empty label and don't need to show them, so I need to filter it and send.delete() request for this headlines.问题是有时我会收到带有空 label 的标题并且不需要显示它们,因此我需要对其进行过滤并发送.delete() 请求以获取此标题。 I tried something like this( The idea was to add
.pipe
before subscribe
and call inside another subscribe.) Something like that我试过这样的事情(想法是在订阅之前添加
.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);
}
but not sure that it's good idea.但不确定这是个好主意。 Which method would be better here?
这里哪种方法更好?
You could use RxJS switchMap
operator to map from one observable to another and forkJoin
function to combine multiple observables.您可以使用 RxJS
switchMap
运算符到 map 从一个可观察对象到另一个,然后forkJoin
function 组合多个可观察对象。 I've also used iif
(with of
) function to check if there are any empty headline
s to be deleted.我还使用了
iif
(with of
) function 来检查是否有要删除的空headline
。
But I fail to understand the condition you're using at the moment.但我不明白你目前使用的条件。 It seems you're removing all the
headline
elements with empty label
property while invoking delete
on the rest.在 rest 上调用
delete
时,您似乎正在删除所有具有空label
属性的headline
元素。 So essentially you're calling delete
on all the valid elements.所以本质上你是在所有有效元素上调用
delete
。 Perhaps it must be adjusted.也许它必须调整。
Try the following尝试以下
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)
);
}
well, ..headline.label.trim()
definitely isn't a good idea, because the double !
好吧,
..headline.label.trim()
绝对不是一个好主意,因为 double !
will delete all headlines that are NOT empty.将删除所有不为空的标题。 also that
map
should be a tap
.还有
map
应该是一个tap
。
so for the complete pipe:所以对于完整的 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);
In a real scenario, i'd leave this to be handled by the backend.在真实场景中,我将把它留给后端处理。 But tbh, this is strongly opinionated, as there is no objective right/wrong here.
但是,这是强烈的观点,因为这里没有客观的对/错。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.