这个问题非常微妙,但显然很重要。鉴于您的代码:
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——它只是忽略响应。这是因为 Promise 是不可取消的。
相反,我强烈推荐使用 RxJS's AjaxObservable
,它是可取消的:
Observable.ajax.getJSON('//api.github.com/users/redux-observable')
这可以通过多种方式导入。如果你已经导入了所有的 RxJS a 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))
);
可以在这里找到一个工作演示:https ://jsbin.com/podoke/edit?js,output