简体   繁体   English

如何取消 redux-saga 中正在运行的网络请求?

[英]How to cancel a running network request in redux-saga?

I have a saga:我有一个传奇:

function* sagaOne() {
   yield call(apiOne);
   yield call(apiTwo);
   yield call(apiThree);
}

function* sagaTwo() {
   try {
      yield all(users.map((user) => call(sagaOne, user));
      yield put(successAction);
   } catch (err) {
     yield put(errAction);
   }
}

function* sagaThree() {
   const task = yield fork(sagaTwo);
   yield take(CancelAction);
   yield cancel(task);
}

My problem is - when sagaThree fires, it forks sagaTwo .我的问题是 - 当sagaThree触发时,它会分叉sagaTwo If I dispatch cancel the action and sagaOne is already in a deeper state - apiOne call already resolved and apiTwo started, the whole request is not canceled.如果我调度取消操作并且sagaOne已经在更深的 state - apiOne调用已经解决并且apiTwo开始,则整个请求不会被取消。

Question: how to properly cancel a "deeper", "nested" task (sagaOne), when it's already at 2nd yield or 3rd?问题:如何正确取消“更深”、“嵌套”任务(sagaOne),当它已经处于第二次或第三次时?

Summing up: cancellation works only if I cancel the task immediately after start and none of the apiTwo hasn't started yet.总结:仅当我在启动后立即取消任务并且没有任何apiTwo尚未启动时,取消才有效。 If it goes deeper, the cancellation doesn't work and every call inside every sagaOne resolves.如果它更深入,取消将不起作用,并且每个sagaOne中的每个调用都会解决。

For functions which return Promise results, you can plug your own cancellation logic by attaching a [CANCEL] to the promise对于返回 Promise 结果的函数,您可以通过将[CANCEL]附加到 promise 来插入您自己的取消逻辑

More info on cancelling redux-saga tasks here .有关取消 redux-saga 任务的更多信息,请点击此处

So we need to enrich promise returned by axios with a method which will be called by redux-saga upon cancelation and will cancel outgoing xhr request.因此,我们需要丰富 axios 返回的 promise 方法,该方法将在取消时由 redux-saga 调用,并将取消传出的 xhr 请求。 Here you can find relevant axios documentation.在这里您可以找到相关的 axios 文档。

OK, let's apply this to our api call:好的,让我们将其应用于我们的 api 调用:

import axios from 'axios';
import { CANCEL } from 'redux-saga'

const CancelToken = axios.CancelToken;

const apiOne = () => {
  const source = CancelToken.source();
  const promise = axios.post('url', {
    cancelToken: source.token
  });

  promise[CANCEL] = () => source.cancel();
  return promise;
};

Now once sagaOne is cancelled the api call will be cancelled as well (if it wasn't completed yet of course).现在一旦sagaOne被取消,api 调用也将被取消(当然,如果它还没有完成)。


This is the basic idea.这是基本思想。 You can extract common logic into wrapper or maybe adapter, so you don't need to do it in each api function.您可以将通用逻辑提取到包装器或适配器中,因此您不需要在每个 api function 中执行此操作。 You can also create a cancel token by passing an executor function to the CancelToken constructor.您还可以通过将执行程序 function 传递给CancelToken构造函数来创建取消令牌。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM