我们将扫描运算符用于表格中的“加载更多”按钮。使用扫描运算符,我们仅将新结果与先前的结果进行累加。 但是,我们遇到了一些意外的行为。
为简单起见,假设我们有以下代码:
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能够使内部可观察的对象变平,其中将扫描运算符引入其中。
谢谢!
答案 0 :(得分:1)
不同的原因是因为在第一种情况下:
interval(1000).pipe(
mergeMap(_ => fakeRequest),
scan<string>((allResponses, currentResponse) => [...allResponses, currentResponse], []),
)
您正在 scan
控制 mergeMap
内创建的所有可观察量的排放。
然而,在第二种情况下:
interval(1000).pipe(
mergeMap(_ => fakeRequest.pipe(
scan<string>((allResponses, currentResponse) => [...allResponses, currentResponse], []),
)),
)
您正在scan
控制一个 observable 的发射,它只发射一次!
本质上,mergeMap()
是一个多次发射的源。 fakeResponse
observable 是一个只发出一次的源。
我从您的评论中看到,您希望在响应下移动 scan
的原因是希望在您的服务中执行 scan
,因此个人消费者不需要这样做。我知道这是一个老问题,所以也许您现在已经想通了,但是您当然可以通过添加 .pipe(scan(...))
.