簡體   English   中英

使用takeUntil在Redux-observable中取消異步請求的預期行為是什么

[英]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))
                );

https://github.com/ReactiveX/rxjs/issues/1732

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM