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

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

相关推荐
崔庆才丨静觅1 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了2 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅2 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅2 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅3 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment3 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅3 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊3 小时前
jwt介绍
前端
爱敲代码的小鱼3 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax