【发布时间】:2021-02-11 04:11:36
【问题描述】:
我们将扫描运算符用于表格中的“加载更多”按钮。使用扫描运算符,我们只是将新结果与之前的结果相加。 但是,我们遇到了一些意想不到的行为。
为了简化,假设我们有以下代码:
const fakeRequest = of('response').pipe(delay(2000));
interval(1000).pipe(
mergeMap(_ => fakeRequest),
scan<string>((allResponses, currentResponse) => [...allResponses, currentResponse], []),
).subscribe(console.log);
产生:
["response"]
["response", "response"]
["response", "response", "response"]
["response", "response", "response", "response"]
...
同时,如果我们只是将扫描运算符移动到 mergeMap/switchMap 运算符中:
interval(1000).pipe(
mergeMap(_ => fakeRequest.pipe(
scan<string>((allResponses, currentResponse) => [...allResponses, currentResponse], []),
)),
).subscribe(console.log);
我们得到以下结果:
["response"]
["response"]
["response"]
["response"]
...
第二个例子中没有执行扫描操作符。我希望 switchMap/mergeMap 只是将内部 observable 展平,其中将扫描运算符通过管道输送到其中。
- 这是期望的行为吗?
- 如果是这样,谁能解释为什么会这样?
- 如果是这样,是否有其他方法/解决方法可以在 mergeMap 或 switchMap 运算符中实现相同的行为?
谢谢!
【问题讨论】:
-
我认为这与 scan() 处理发出的数据的事实有关,mergeMap 在将值映射到外部 observable 之前完成订阅内部 observable 的工作。如果您将 scan() 运算符放在 fakeRequest 声明语句中,可能会更清楚的是,扫描没有得到任何值,因为 of().pipe(delay()) 从未订阅发出 'response '。
-
您的第一个示例运行良好,为什么要切换到第二个示例
-
@FanCheung 1. 因为我们的 fakeRequest observable 来自服务。我们希望在我们的数据服务中包含扫描功能,因为它属于那里。但是,出于某种原因,我们不得不在页面组件中使用 switchMap。现在我们需要在我们的组件中添加扫描功能,这不是我们想要的,而且是非常意外的行为。我们认为 switchMap 几乎会“切换”到内部的 Observable,包括扫描操作符。 2. 只是想了解这些怪癖。我们没想到内部 observable 的操作符会被“忽略”。
标签: typescript rxjs