[英]What is the expected behaviour Cancelling async request in Redux-observable using takeUntil
我是RXJS的新手,我發現使用takeUntil的Redux-observable取消異步請求非常有用。 但是當我測試它時,我發現即使我們取消了請求,實際的請求仍在繼續。
我有這個JSbin代碼片段要測試。
https://jsbin.com/hujosafocu/1/edit?html,js,輸出
即使您通過單擊取消(多次)按鈕取消了請求,實際的請求也不會取消。
我不確定這應該是..如果是,那么取消異步請求意味着什么。 我有點困惑..請分享一些想法..
任何對此的回應將不勝感激..謝謝
這個問題非常微妙,但顯然很重要。 鑒於您的代碼:
const fetchUserEpic = action$ =>
action$.ofType(FETCH_USER)
.delay(2000) // <-- while we're waiting, there is nothing to cancel!
.mergeMap(action =>
Observable.fromPromise(
jQuery.getJSON('//api.github.com/users/redux-observable', data => {
alert(JSON.stringify(data));
})
)
.map(fetchUserFulfilled)
.takeUntil(action$.ofType(FETCH_USER_CANCELLED))
);
最重要的是.delay(2000)
。 這就是說,“直到2000毫秒之后,才將動作發送給鏈的其余部分”。 由於您的.takeUntil(action$.ofType(FETCH_USER_CANCELLED))
取消邏輯位於mergeMap
的投影函數內部,因此它尚未偵聽FETCH_USER_CANCELLED
因為尚無要取消的內容!
如果您確實想在進行ajax調用之前引入一個任意延遲,但同時取消延遲或掛起的ajax(如果到達那里),則可以使用Observable.timer()
const fetchUserEpic = action$ =>
action$.ofType(FETCH_USER)
.mergeMap(action =>
Observable.timer(2000)
.mergeMap(() =>
Observable.fromPromise(
jQuery.getJSON('//api.github.com/users/redux-observable', data => {
alert(JSON.stringify(data));
})
)
.map(fetchUserFulfilled)
)
.takeUntil(action$.ofType(FETCH_USER_CANCELLED))
);
我想你真的不希望引入的任意時間后你的Ajax在現實世界的應用程序調用之前,在這種情況下,這個問題不會存在,並且在文檔例子是一個很好的起點參考。
要注意的另一件事是,即使沒有延遲或計時器,從代碼中取消ajax請求也不會取消真正的基礎XMLHttpRequest -它只是忽略響應。 這是因為承諾是無法取消的。
相反,我強烈建議使用RxJS的AjaxObservable
,它可以取消:
Observable.ajax.getJSON('//api.github.com/users/redux-observable')
這可以通過幾種方式導入。 如果您已經導入了所有RxJS,請先import 'rxjs';
,可以按預期使用。 否則,還有其他幾種方法:
import { ajax } from 'rxjs/observable/dom/ajax';
ajax.getJSON('/path/to/thing');
// or
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/dom/ajax';
Observable.ajax.getJSON('/path/to/thing');
重要的是要記住,就像所有Observable工廠一樣, Observable.ajax
是惰性的,這意味着它只有在有人訂閱后才發出AJAX請求! 就像jQuery.getJSON
。
因此,您可以像這樣將其放在一起:
const fetchUserEpic = action$ =>
action$.ofType(FETCH_USER)
.mergeMap(action =>
Observable.timer(2000)
.mergeMap(() =>
Observable.ajax.getJSON('//api.github.com/users/redux-observable')
.do(data => alert(JSON.stringify(data)))
.map(fetchUserFulfilled)
)
.takeUntil(action$.ofType(FETCH_USER_CANCELLED))
);
一個有效的演示可以在這里找到: https : //jsbin.com/podoke/edit?js,output
這可能會在將來對某人有所幫助。
像上面提到的jayphelps一樣,更好的解決方案是使用RXjs AjaxObservable,因為它取消了實際的XMLHttpRequest而不是忽略響應。
但是目前RxJS v5上存在一些問題“ RxJS Observable.ajax跨域問題”
我發現好的解決方案是“允許繞過默認配置”,如下所示:
const fetchUserEpic = action$ =>
action$.ofType(FETCH_USER)
.mergeMap(action =>
Observable.timer(2000)
.mergeMap(() =>
Observable.ajax({
url:`//api.github.com/users/redux-observable`,
crossDomain: true
})
.do(data => alert(JSON.stringify(data)))
.map(fetchUserFulfilled)
)
.takeUntil(action$.ofType(FETCH_USER_CANCELLED))
);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.