欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > IT业 > 探索 JavaScript 中的 AbortController API:不仅仅是中断 HTTP 请求

探索 JavaScript 中的 AbortController API:不仅仅是中断 HTTP 请求

2024/10/23 0:12:21 来源:https://blog.csdn.net/weixin_44733660/article/details/142996932  浏览:    关键词:探索 JavaScript 中的 AbortController API:不仅仅是中断 HTTP 请求

在 JavaScript 中处理异步操作时,通常需要灵活的控制机制来中止任务。AbortController API 提供了一个强大且通用的方式来终止异步操作,不仅可以中断 HTTP 请求,还可以应用于多种异步任务,如事件监听、流操作等。在本文中,我们将详细探讨 AbortController 的使用场景、AbortSignal 的静态方法、事件处理中的中止机制,以及在实际开发中的一些最佳实践。

AbortController 简介

AbortController 是 JavaScript 中的全局类,专门用于管理和中止异步操作。通过创建一个 AbortController 实例,我们可以获取两个核心功能:

  1. signal 属性:用于监控是否有中止信号发出,能够传递给异步操作,比如 fetch 请求或事件监听器。
  2. .abort() 方法:可以随时手动触发中止信号,进而取消异步操作。

基本用法如下:

const controller = new AbortController();
const signal = controller.signal;fetch('/api/data', { signal }).then(response => response.json()).catch(error => {if (error.name === 'AbortError') {console.log('Fetch request was aborted');} else {console.error('Fetch error:', error);}});// 取消请求
controller.abort();

事件监听器的取消

在事件处理中,我们可以通过将 AbortController.signal 传递给 addEventListener 的第三个参数,使得在中止时自动移除事件监听器:

const controller = new AbortController();
const button = document.querySelector('#myButton');button.addEventListener('click', () => {console.log('Button clicked');
}, { signal: controller.signal });// 在某个条件下中止事件监听
controller.abort();

这样,当调用 controller.abort() 时,按钮的点击事件监听器会被自动移除,避免冗余的事件绑定和内存泄漏。

Fetch 请求的中断

fetch 请求原生支持 AbortSignal,可以在请求发出后随时中断:

const controller = new AbortController();fetch('/api/long-running-task', { signal: controller.signal }).then(response => response.json()).catch(err => {if (err.name === 'AbortError') {console.log('Fetch request aborted');} else {console.error('Fetch failed:', err);}});// 稍后取消请求
setTimeout(() => {controller.abort();
}, 5000);  // 5秒后取消请求

在网络请求延时过长或用户切换页面等场景下,中断 fetch 请求可以显著提升用户体验。

Axios 请求的中断

从 v0.22.0 开始,Axios 支持以 fetch API 方式—— AbortController 取消请求:

const controller = new AbortController();axios.get('/foo/bar', {signal: controller.signal
}).then(function(response) {//...
});
// 取消请求
controller.abort()
  • 当然还可以使用 CancelToken 取消一个请求,但需要注意的是此 API 从 v0.22.0 开始已被弃用,不应在新项目中使用。
const CancelToken = axios.CancelToken;
const source = CancelToken.source();axios.get('/user/12345', {cancelToken: source.token
}).catch(function (thrown) {if (axios.isCancel(thrown)) {console.log('Request canceled', thrown.message);} else {// 处理错误}
});axios.post('/user/12345', {name: 'new name'
}, {cancelToken: source.token
})// 取消请求(message 参数是可选的)
source.cancel('Operation canceled by the user.');

Node.js 请求的中断

在 Node.js 环境中,http 模块的请求同样支持使用 AbortSignal 来中止请求。以下是一个简单的示例:

const http = require('http');
const { AbortController } = require('abort-controller');const controller = new AbortController();const req = http.get('http://example.com', { signal: controller.signal }, res => {res.on('data', chunk => {console.log(`Data: ${chunk}`);});
});setTimeout(() => {controller.abort();console.log('Request aborted');
}, 5000);  // 5秒后中止请求

这在处理长时间的 HTTP 请求时非常有用,尤其是需要通过中断请求来节省资源。

AbortSignal 的静态方法

AbortSignal 还提供了两个静态方法,timeoutany,可以增强中止操作的灵活性:

  1. AbortSignal.timeout(duration):可以设置一个自动超时的中止信号。
const signal = AbortSignal.timeout(5000);  // 5秒后自动中止fetch('/api/data', { signal }).catch(err => {if (err.name === 'AbortError') {console.log('Fetch request timed out');}});
  1. AbortSignal.any([signal1, signal2, ...]):允许组合多个中止信号,任何一个信号触发中止,都会终止任务。
const controller1 = new AbortController();
const controller2 = new AbortController();const signal = AbortSignal.any([controller1.signal, controller2.signal]);fetch('/api/data', { signal }).catch(err => {if (err.name === 'AbortError') {console.log('Fetch request aborted by one of the signals');}});// 任意一个 controller 调用 abort 都会中止 fetch 请求
controller1.abort();

取消流操作

在现代 JavaScript 中,AbortController 也可以用于中止可写流(WritableStream)的操作。在处理流式数据时,这种中止机制非常重要,可以有效管理数据传输和资源消耗:

const controller = new AbortController();
const stream = new WritableStream({write(chunk, controller) {// 写入逻辑},abort(reason) {console.log('Stream aborted:', reason);}
}, { signal: controller.signal });// 中止流操作
controller.abort('Manual abort');

中止任何逻辑

AbortController 不仅限于终止网络请求,还可以在任意可中止的逻辑中使用。比如,我们可以在 ORM 事务处理中使用它:

async function performTransaction() {const controller = new AbortController();try {await startTransaction({ signal: controller.signal });// 事务逻辑} catch (error) {if (error.name === 'AbortError') {console.log('Transaction aborted');}}controller.abort();
}

中止错误处理

当中止事件发生时,AbortSignal 会附带一个 AbortError,开发者可以根据不同的中止原因进行错误处理。例如,我们可以传递一个自定义的中止原因并在错误处理中使用:

const controller = new AbortController();
controller.abort('Operation was manually cancelled');fetch('/api/data', { signal: controller.signal }).catch(err => {if (err.name === 'AbortError') {console.log('Fetch aborted with reason:', err.message);  // 输出自定义原因}});

兼容性

AbortController 具有良好的兼容性,几乎所有现代浏览器都支持它。此外,Node.js 也通过实验性功能实现了对 AbortController 的支持。它已经成为开发者工具箱中不可或缺的部分。

总结

AbortController 是一个非常有用且灵活的 API,适用于多种异步操作的中止和管理。无论是取消 HTTP 请求、事件监听,还是流式数据处理,AbortController 都能为开发者提供精细的控制能力。通过合理使用它,我们可以更好地优化代码的健壮性和用户体验。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com