什么是预期行为使用takeUntil取消Redux-observable中的异步请求 [英] What is the expected behaviour Cancelling async request in Redux-observable using takeUntil

查看:229
本文介绍了什么是预期行为使用takeUntil取消Redux-observable中的异步请求的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

i am new to RXJS, i found Redux-observable canceling async request using takeUntil is very useful. but while i was testing it i found that the actual request is still going on even though we cancel the request..

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

i have this JSbin code snippet to test.

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

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

here the actual request is not canceling, even if you cancel the request by clicking the cancel (multiple times) button.

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

i am not sure this is how it should be.. if yes, then what does it meant by canceling async request. I am bit confused.. Please share some thoughts..

任何回复都会非常感谢..谢谢

any respond to this will greatly appreciate.. thanks

推荐答案

问题非常微妙,但显然很重要。给出你的代码:

The issue is very subtle, but obviously important. Given your code:

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)。这就是说,直到2000ms之后才开始向链的其余部分发出动作。因为您的 .takeUntil(action $ .ofType(FETCH_USER_CANCELLED))取消逻辑位于 mergeMap 的投影函数中,它还没有收听 FETCH_USER_CANCELLED ,因为还没有什么可以取消!

The kicker is the .delay(2000). What this is saying is, "don't emit the action to the rest of the chain until after 2000ms". Because your .takeUntil(action$.ofType(FETCH_USER_CANCELLED)) cancellation logic is inside the mergeMap's projection function, it is not yet listening for FETCH_USER_CANCELLED because there is nothing to cancel yet!

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

If you really want to introduce an arbitrary delay before you make the ajax call, but cancel both the delay OR the pending ajax (if it reaches there) you can use 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调用真实世界的应用程序,在这种情况下,这个问题将不存在,并且文档中的示例是一个很好的起始参考。

I imagine you don't really want to introduce the arbitrary delay before your ajax calls in real-world apps, in which case this problem won't exist and the example in the docs is a good starting reference.

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

Another thing to note is that even without the delay or timer, cancelling the ajax request from your code doesn't cancel the real underlying XMLHttpRequest--it just ignores the response. This is because Promises are not cancellable.

相反,我强烈建议使用RxJS的 AjaxObservable ,其中可取消:

Instead, I would highly recommend using RxJS's AjaxObservable, which is cancellable:

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

这可以通过多种方式导入。如果您已经导入了所有RxJS la import'rxjs'; ,它可以按预期使用。否则,还有其他几种方法:

This can be imported in several ways. If you're already importing all of RxJS a la import 'rxjs';, it's available as expected. Otherwise, there are several other ways:

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 lazy 意味着在有人订阅之前它不会发出AJAX请求!其中 jQuery.getJSON 立即生成。

It's important to remember, like all the Observable factories, Observable.ajax is lazy meaning it does not make the AJAX request until someone subscribes to it! Where as jQuery.getJSON makes it right away.

所以你可以像这样把它放在一起:

So you can put it together like this:

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

A working demo of this can be found here: https://jsbin.com/podoke/edit?js,output

这篇关于什么是预期行为使用takeUntil取消Redux-observable中的异步请求的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆