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));

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

相关推荐
_Kayo_31 分钟前
CSS BFC
前端·css
二哈喇子!1 小时前
Vue3 组合式API
前端·javascript·vue.js
二哈喇子!3 小时前
Vue 组件化开发
前端·javascript·vue.js
chxii3 小时前
2.9 插槽
前端·javascript·vue.js
姑苏洛言4 小时前
扫码点餐小程序产品需求分析与功能梳理
前端·javascript·后端
Freedom风间4 小时前
前端必学-完美组件封装原则
前端·javascript·设计模式
江城开朗的豌豆4 小时前
React表单控制秘籍:受控组件这样玩就对了!
前端·javascript·react.js
一枚前端小能手4 小时前
📋 代码片段管理大师 - 5个让你的代码复用率翻倍的管理技巧
前端·javascript
国家不保护废物5 小时前
Web Worker 多线程魔法:告别卡顿,轻松实现图片压缩!😎
前端·javascript·面试
接着奏乐接着舞。5 小时前
如何在Vue中使用拓扑图功能
前端·javascript·vue.js