什么是预期行为使用takeUntil

时间:2016-11-23 06:00:41

标签: javascript asynchronous redux rxjs redux-observable

我是RXJS的新手,我发现使用takeUntil的Redux-observable取消异步请求非常有用。但是当我测试它时,我发现即使我们取消了请求,实际的请求仍在继续。

我有这个JSbin代码片段来测试。

https://jsbin.com/hujosafocu/1/edit?html,js,output

此处即使您通过单击取消(多次)按钮取消请求,实际请求也不会取消。

我不确定它应该如何...如果是,那么取消异步请求意味着什么。我有点困惑..请分享一些想法..

任何对此的回应都会非常感谢..谢谢

2 个答案:

答案 0 :(得分:4)

问题非常微妙,但显然很重要。鉴于您的代码:

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)。这就是说,&#34;直到2000ms后才会向链的其余部分发出动作。由于您的.takeUntil(action$.ofType(FETCH_USER_CANCELLED))取消逻辑位于mergeMap投影函数中,因此尚未收听FETCH_USER_CANCELLED,因为尚无取消!

如果确实想要在进行ajax调用之前引入任意延迟,但是取消延迟或挂起的ajax(如果它到达那里)你可以使用Observable.timer() < / p>

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调用现实世界的应用程序之前引入任意延迟,在这种情况下,这个问题不会存在而且{{ 3}}是一个很好的起始参考。

另外需要注意的是,即使没有延迟或计时器,从代码中取消ajax请求也不会取消真正的底层XMLHttpRequest - 它只是忽略了响应。这是因为Promise不可取消。

相反,我强烈建议使用RxJS&#39; AjaxObservable,其中 可取消:

Observable.ajax.getJSON('//api.github.com/users/redux-observable')

可以通过多种方式导入。如果您已经导入了所有RxJS la 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))
    );

可在此处找到相关的工作演示:example in the docs

答案 1 :(得分:0)

这可能会对将来有所帮助..

与上面提到的jayphelps一样,更好的解决方案是使用RXjs AjaxObservable,因为它取消了实际的XMLHttpRequest而不是忽略响应。

但目前RxJS v5“RxJS Observable.ajax跨域问题”存在一些问题

我发现的好解决方案是“允许绕过默认配置” 如下所示:

{{1}}

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