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

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

相关推荐
城市的稻草人VS12 小时前
rust【日志库】
前端·rust
问心无愧051312 小时前
ctf show web 入门258
android·前端·笔记
xwjalyf12 小时前
javascript数组 forEach,filter,some,every,map,find,reduce的用法与区别
开发语言·javascript·json·ecmascript
海兰12 小时前
【小程序】 贪吃蛇(Next.js+WebSocket+SQLite + Prisma ORM)
javascript·websocket·小程序
qq_25183645712 小时前
基于java Web 耗材购置与维修网络申报审批系统设计与实现
java·开发语言·前端
UXbot12 小时前
企业AI开发工具:界面自动生成与前端代码交付能力详解
前端·人工智能·交互·web app·ui设计
专业技术员!!!!12 小时前
陪玩系统前端核心功能详解|线上线下陪玩平台开发方案
前端·陪玩系统·电竞陪玩
英俊潇洒美少年12 小时前
前端主流状态管理全家桶:Vuex/Pinia/Redux/Zustand/MobX 从入门到原理、实战、面试全解
前端·面试·职场和发展
JiaWen技术圈12 小时前
next.js 开发中的水合(Hydration)问题
javascript
Maddie_Mo12 小时前
Pi Agent Web 使用教程:把本地 Pi Coding Agent 搬进浏览器
android·java·前端·人工智能·ai