JS如何优雅的中断正在执行的异步函数

在 JavaScript 里,若要优雅地中断正在执行的异步函数,可依据不同的异步实现方式采用不同的方法,下面详细介绍几种常见情况。

1. 使用 AbortController 中断 fetch 请求

AbortController 是一个内置于浏览器和 Node.js 中的 API,能用于取消 fetch 请求等异步操作。

javascript 复制代码
const controller = new AbortController();
const signal = controller.signal;

// 模拟一个 fetch 请求
fetch('https://example.com/api/data', { signal })
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('请求已被取消');
    } else {
      console.error('请求出错:', error);
    }
  });

// 在需要的时候取消请求
controller.abort();

2. 在自定义异步函数中使用 AbortController

若你有自定义的异步函数,也能结合 AbortController 来实现中断功能。

javascript 复制代码
function customAsyncFunction(signal) {
  return new Promise((resolve, reject) => {
    const intervalId = setInterval(() => {
      console.log('异步操作正在执行...');
      if (signal.aborted) {
        clearInterval(intervalId);
        reject(new DOMException('操作已被取消', 'AbortError'));
      }
    }, 1000);
  });
}

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

customAsyncFunction(signal)
  .then(() => console.log('异步操作完成'))
  .catch(error => {
    if (error.name === 'AbortError') {
      console.log('异步操作已被取消');
    } else {
      console.error('异步操作出错:', error);
    }
  });

// 在需要的时候取消操作
setTimeout(() => {
  controller.abort();
}, 3000);

当然也可以使用一个变量来控制自定义异步函数的中断,这是一种较为基础且直观的方式。下面是使用变量来控制异步函数中断的示例代码:

javascript 复制代码
function customAsyncFunction() {
    let isAborted = false;

    return {
        promise: new Promise((resolve, reject) => {
            const intervalId = setInterval(() => {
                console.log('异步操作正在执行...');
                if (isAborted) {
                    clearInterval(intervalId);
                    reject(new Error('操作已被取消'));
                }
            }, 1000);
        }),
        abort: () => {
            isAborted = true;
        }
    };
}

const asyncTask = customAsyncFunction();

asyncTask.promise
   .then(() => console.log('异步操作完成'))
   .catch(error => {
        console.error('异步操作出错:', error.message);
    });

// 在需要的时候取消操作
setTimeout(() => {
    asyncTask.abort();
}, 3000);

使用变量控制和 AbortController 对比

  • 使用变量控制

    • 优点:简单直接,不需要额外了解新的 API,适合小型项目或者简单的异步控制场景。
    • 缺点:缺乏标准化,在不同的异步函数中可能需要重复实现类似的逻辑,代码的可维护性和扩展性较差。当项目规模变大,管理多个异步操作的中断状态会变得复杂。
  • 使用 AbortController

    • 优点 :是 JavaScript 官方标准化的 API,具有统一的使用方式和错误处理机制。可以在不同的异步操作(如 fetch 请求、自定义异步函数等)中复用,增强了代码的可维护性和一致性。在与第三方库或框架集成时,也更容易与其他使用 AbortController 的代码进行交互。
    • 缺点 :需要额外学习 AbortController 的使用方法,对于初学者来说可能有一定的学习成本。

使用变量控制能满足基本的异步函数中断需求,但在复杂的项目中,AbortController 是更优雅和推荐的选择。

3. 使用 Promise.race 实现超时中断

你可以利用 Promise.race 来实现超时中断异步操作。

javascript 复制代码
function asyncOperation() {
  return new Promise((resolve) => {
    setTimeout(() => {
      resolve('操作完成');
    }, 5000);
  });
}

function timeout(ms) {
  return new Promise((_, reject) => {
    setTimeout(() => {
      reject(new Error('操作超时'));
    }, ms);
  });
}

Promise.race([asyncOperation(), timeout(3000)])
  .then(result => console.log(result))
  .catch(error => console.error(error.message));

以上这些方法能帮助你在不同场景下优雅地中断正在执行的异步函数。

相关推荐
前端小趴菜0533 分钟前
React-React.memo-props比较机制
前端·javascript·react.js
摸鱼仙人~2 小时前
styled-components:现代React样式解决方案
前端·react.js·前端框架
sasaraku.2 小时前
serviceWorker缓存资源
前端
RadiumAg3 小时前
记一道有趣的面试题
前端·javascript
yangzhi_emo3 小时前
ES6笔记2
开发语言·前端·javascript
yanlele3 小时前
我用爬虫抓取了 25 年 5 月掘金热门面试文章
前端·javascript·面试
中微子5 小时前
React状态管理最佳实践
前端
烛阴5 小时前
void 0 的奥秘:解锁 JavaScript 中 undefined 的正确打开方式
前端·javascript
中微子5 小时前
JavaScript 事件与 React 合成事件完全指南:从入门到精通
前端
Hexene...5 小时前
【前端Vue】如何实现echarts图表根据父元素宽度自适应大小
前端·vue.js·echarts