buttonClicked$.pipe(
switchMap(value=>makeRequest1),
switchMap(responseOfRequest1=>makeRequest2))
.subscribe()
我需要依次发出2个http请求,如果单击按钮,则中止下游待处理的请求。上面的代码是正确的方法吗?我了解一次新点击将取消待处理的request1
。如果点击发生在request2
期间,request2
也会被取消吗?
答案 0 :(得分:1)
switchMap
运算符仅在从其上游Observable(即makeRequest1
)接收到下一个事件时才取消其内部Observable,而不是在源Observable发出时(即buttonClicked$
)取消其内部Observable。因此,请考虑以下事件顺序:
first button click
first request 1 sent
first response to request 1 received
first request 2 sent
second button click
second request 1 sent
first response to request 2 received
second response to request 1 received
在这种情况下,因为在接收到对请求1的第二个响应之前就已经收到了对请求2的响应,所以即使在完成请求2之前第二次单击按钮,也不会取消请求2。
如果请求1在请求2收到响应之前发出其第二个响应,则请求2被取消。但是请注意,并不是单击按钮本身会取消它,而是发出请求1取消它。
如果您希望在单击按钮时可靠地取消两个请求,则两个请求都必须在同一switchMap
内进行:
buttonClicked$.pipe(
switchMap(clickValue => makeRequest1(clickValue).pipe(
mergeMap(request1Value => makeRequest2(request1Value)))
).subscribe(request2Value => /* ... */);
答案 1 :(得分:1)
这是正确的行为,因为switchMap
仅在收到next
通知时才从其内部Observable取消订阅。这意味着当您有两个switchMap
时,第一个必须先发出才能触发第二个中的取消订阅。
您可以通过仅使用一个switchMap
并将第二个makeRequest2
调用与makeRequest1
放在一个链中来避免这种情况。
buttonClicked$.pipe(
switchMap(value => makeRequest1(value).pipe(
mergeMap(responseOfRequest1 => makeRequest2(responseOfRequest1)),
)),
.subscribe()
通过这种方式,当buttonClicked$
发出信号时,switchMap
便从其内部Observable取消订阅,该内部Observable也取消了mergeMap
的订阅,如果第二个呼叫仍未决,它将取消第二个呼叫。
答案 2 :(得分:0)
是的,它确实具有一定间隔。我没有通过网络请求对其进行测试。
每单击一次,第二个可观察间隔就会重新开始。
const { fromEvent, interval, of } = rxjs;
const { switchMap } = rxjs.operators;
const btn = document.getElementById('btn');
const result = document.getElementById('result');
const click$ = fromEvent(btn, 'click');
click$
.pipe(
switchMap(value => of('Hello')),
switchMap(value => interval(1000))
)
.subscribe(
val => result.innerText = val
)
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.4.0/rxjs.umd.min.js"></script>
<button id="btn">Click Me</button>
<div id="result"></div>