前端如何优雅地中止正在进行的 HTTP 请求

223 阅读3分钟

前端如何优雅地中止正在进行的 HTTP 请求

前言

在开发 Web 应用程序时,我们常常遇到需要取消正在进行的 HTTP 请求的场景。比如,用户快速连续点击按钮触发多次请求,或者在页面切换时及时终止未完成的请求以节省资源和避免数据混乱。

今天,就让我们来深入探讨一下如何实现这一功能。

Image

为何要取消 HTTP 请求?

在某些情况下,取消 HTTP 请求是非常必要的。比如,当用户在搜索框中快速连续输入关键词时,每次输入都会触发一个新的搜索请求。

如果不取消之前的请求,就会导致多个不必要的请求同时进行,这不仅会浪费宝贵的网络资源,还可能会使页面显示混乱,甚至影响用户体验。此外,在导航离开当前页面时,取消未完成的请求可以避免在新页面加载完成后,旧请求的响应才返回并错误地修改页面数据。

使用 Axios 实现请求取消

Axios 是一个基于 Promise 的 HTTP 请求库,它提供了很好的取消请求的功能支持。

创建取消令牌

首先,我们需要创建一个取消令牌,该令牌用于标识一个可被取消的请求。

const CancelToken = axios.CancelToken;
let cancel;
const source = CancelToken.source();

发起可取消的请求

在发起请求时,我们将创建的取消令牌作为配置项传递进去。

axios.get('/some/request', {
  cancelToken: source.token
})
.then(response => {
  // 处理响应
})
.catch(error => {
  if (axios.isCancel(error)) {
    console.log('请求已取消', error.message);
  } else {
    // 处理错误
  }
});

取消请求

当需要取消请求时,只需调用取消令牌源的 cancel 方法,并提供取消原因。

if (someCondition) {
  source.cancel('用户取消了请求');
}

使用 Fetch API 实现请求取消

Fetch API 是现代浏览器提供的原生 HTTP 请求解决方案,它同样支持请求取消功能,但需要借助 AbortController

创建 AbortController 实例

AbortController 提供了控制请求取消的能力。我们创建一个实例,并通过其 signal 属性获取取消信号。

const controller = new AbortController();
const signal = controller.signal;

发起可取消的请求

在发起 Fetch 请求时,我们将取消信号作为选项传递给 fetch 函数。

fetch('/some/request', { signal })
  .then(response => {
    // 处理响应
  })
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('请求已取消');
    } else {
      // 处理错误
    }
  });

取消请求

调用 AbortController 实例的 abort 方法即可取消对应的请求。

if (someCondition) {
  controller.abort();
}

注意事项

在实现请求取消功能时,有几点需要注意:

  • • 及时释放资源:取消请求后,应确保释放与该请求相关的资源,如清理定时器、事件监听器等,以避免内存泄漏。
  • • 处理取消后的状态:取消请求可能会导致页面状态不一致,因此需要合理处理取消后的页面状态更新,确保用户体验不受影响。
  • • 兼容性考虑:虽然 Axios 和 Fetch API 都广泛支持现代浏览器,但在使用一些高级功能时,仍需考虑浏览器的兼容性问题,必要时提供降级方案。

掌握如何取消正在进行的 HTTP 请求,能够让你的 Web 应用更加高效、智能和用户友好。

通过合理使用 Axios 或 Fetch API 提供的请求取消功能,你可以轻松应对各种复杂的网络请求场景。