跳到主要内容

redux-saga 中取消 fetch 请求

· 阅读需 2 分钟
youniaogu

redux-saga 中取消 fetch 请求

在阅读本篇文章前,建议先阅读redux-saga 文档,理解基础用法

redux-saga 可以使用cancel取消任务,但并不能取消已经发起的请求。而xhrfetch都提供了取消请求的方法,所以我们可以通过封装fetch,在取消任务的同时取消请求。

1. 关于 fetch 请求的取消

参考AbortController

2. 原理

yield 关键字在被取消时候会抛出错误,所以只需要用generator函数包住fetch请求,在里面通过try catch获取错误,最后取消请求

封装fetch

//fetch.js
function* fetchData(options) {
const controller = new AbortController();

try {
return yield fetchDataWithoutCancel({
...options,
signal: controller.signal,
});
} finally {
controller.abort();
}
}

3. 实际运用

takeLatest结合使用:
function* cancelFetchSaga() {
yield takeLatest('CANCEL_FETCH', function*() {
const data = yield call(fetchData, {
url: 'http://httpstat.us/200?sleep=1000',
}),

console.log(data);
});
}

每当执行cancelFetch任务,上一个未完成任务就会被取消,同时请求也会被取消

使用racedelay实现超时取消请求:
function* cancelFetchSaga() {
yield takeLatest("CANCEL_FETCH", function* () {
const { data, timeout } = yield race({
data: call(fetchData, {
url: "http://httpstat.us/200?sleep=2000",
}),
timeout: delay(1000),
});

if (timeout) {
console.log("fetch canceled!");
} else {
console.log(data);
}
});
}

1s 后请求会被取消

4. 测试用工具

  1. httpstat,可以自定义返回延迟

  2. chrome network 里设置 throtting

pic2