我们使用扫描操作符在我们的表‘加载更多’按钮。使用扫描运算符,我们只积累新的结果与前面的结果。然而,我们遇到了一些意想不到的行为。
为了简化,假设我们有以下代码:
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"]
...
在第二个示例中没有执行扫描操作符。我想切换地图/mergeMap只是将内部可观察到的东西压平,其中有扫描操作符。
谢谢!
发布于 2021-02-10 20:11:36
造成这种差异的原因是,在第一种情况下:
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
从一个可观察到的排放量,这只排放一次!
本质上,mergeMap()
是一个多次发射的源。可观测到的fakeResponse
是一个只发射一次的源。
我从您的评论中看到,您希望将scan
移到响应下的原因,是因为希望在您的服务中执行scan
,因此单个消费者不需要这样做。我知道这是一个老生常谈的问题,所以也许您现在已经知道了,但是您当然可以在服务中执行扫描逻辑(只要您的interval()也在服务中),只需在.pipe(scan(...))
上插入即可。
https://stackoverflow.com/questions/55267378
复制相似问题