2024全方位解析promise

前面我们谈到过 Promise 规范 & PromiseA+ 规范,今天我们来详细仔细谈谈promise,一起探讨关于promise常用的一些知识。

前置内容了解先了解什么是静态方法和实例方法

promise 区分静态方法和实例方法。静态方法:通过 Promise 类直接调用,例如 Promise.all、Promise.resolve 等,主要用于创建和组合 Promise。 实例方法:在 Promise 实例上调用,如 then、catch 和 finally,用于处理 Promise 的结果和状态。

静态方法

静态方法是与类本身相关的方法,而不是与类的实例相关。也就是说,你可以直接通过类名来调用静态方法,而不需要先创建类的实例。

定义与使用

js 复制代码
class MyClass {
    static staticMethod() {
        console.log("这是一个静态方法");
    }
}

// 调用静态方法
MyClass.staticMethod(); // 输出: 这是一个静态方法

特点

  • 静态方法不能通过类的实例访问。
  • 通常用于工具函数、工厂方法或者与类本身相关的逻辑。
  • 在静态方法内部不能访问实例属性和实例方法,因为它们没有实例上下文。

实例方法

实例方法是与类的实例相关联的方法。你必须先创建类的实例,然后才能调用实例方法。

定义与使用

js 复制代码
class MyClass {
    constructor(name) {
        this.name = name;
    }

    instanceMethod() {
        console.log(`这是一个实例方法,名称是: ${this.name}`);
    }
}

// 创建实例
const myInstance = new MyClass("实例");

// 调用实例方法
myInstance.instanceMethod(); // 输出: 这是一个实例方法,名称是: 实例

特点

  • 实例方法可以访问实例的属性和其他实例方法。
  • 实例方法通常用于操作实例的状态或执行与具体实例相关的行为。
  • 每个实例都有自己的方法副本。

总结

  • 静态方法:不依赖于类的实例,直接通过类名调用,主要用于与类相关的功能。
  • 实例方法:依赖于类的实例,属于特定的对象,能够操作对象的属性和状态。

promise 定义/描述

一个 Promise 是一个代理,它代表一个在创建 promise 时不一定已知的值。它允许你将处理程序与异步操作的最终成功值或失败原因关联起来。这使得异步方法可以像同步方法一样返回值:异步方法不会立即返回最终值,而是返回一个 promise,以便在将来的某个时间点提供该值(MDN描述

Promise三种状态

  • 待定(pending):初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled):意味着操作成功完成。
  • 已拒绝(rejected):意味着操作失败

基本使用

  • 创建 Promise

    typescript 复制代码
    const promise = new Promise((resolve, reject) => {
      // 异步操作
      if (/* 操作成功 */) {
        resolve('Success');
      } else {
        reject('Error');
      }
    });
  • 消费 Promise

    • .then() 方法用于指定当 Promise 成功时的回调函数。
    • .catch() 方法用于指定当 Promise 失败时的回调函数。
    typescript 复制代码
    promise
      .then(result => console.log(result))
      .catch(error => console.error(error));

链式调用

  • Promise 支持链式调用 ,即在 .then().catch() 方法中返回一个新的 Promise ,可以继续调用 .then().catch()

    typescript 复制代码
    promise
      .then(result => {
        return new Promise((resolve, reject) => {
          setTimeout(() => resolve(result + ' processed'), 1000);
        });
      })
      .then(processedResult => console.log(processedResult))
      .catch(error => console.error(error));

并发处理

  • Promise.all() 当所有 Promise 都成功时返回一个包含所有结果的数组;如果任何一个 Promise 失败,则返回失败的那个 Promise

    typescript 复制代码
    const promises = [promise1, promise2, promise3];
    Promise.all(promises)
      .then(values => console.log(values))
      .catch(error => console.error(error));
  • Promise.race() 返回最先改变状态的 Promise 的结果。

    typescript 复制代码
    const promises = [promise1, promise2, promise3];
    Promise.race(promises)
      .then(value => console.log(value))
      .catch(error => console.error(error));

Promise.allSettled()

  • Promise.allSettled() :与 Promise.all() 类似,但它不会因为某个 Promise 的拒绝而立即拒绝整个集合。相反,它等待所有 Promise 都完成(无论是成功还是失败),并返回一个包含每个 Promise 结果的数组。

    typescript 复制代码
    const promises = [
      fetch('/api/user'),
      fetch('/api/posts')
    ];
    
    Promise.allSettled(promises)
      .then(results => results.forEach(result => {
        if (result.status === 'fulfilled') {
          console.log(result.value); // 成功的结果
        } else {
          console.error(result.reason); // 失败的原因
        }
      }));

Promise.any()

  • Promise.any() :返回一个 Promise,该 Promise 在其中一个输入的 Promise 成功时解决,或者所有输入的 Promise 都失败时拒绝。

    typescript 复制代码
    const promises = [
      fetch('/api/user').then(response => response.ok ? response : Promise.reject()),
      fetch('/api/backupUser').then(response => response.ok ? response : Promise.reject())
    ];
    
    Promise.any(promises)
      .then(user => console.log('User fetched:', user))
      .catch(errors => console.error('All requests failed:', errors));

Promise.race() 的改进

  • 虽然 Promise.race() 的基本行为没有改变,但在实际应用中,开发者可以通过组合使用 Promise.race()Promise.all() 来实现超时控制等高级功能。

    typescript 复制代码
    const timeout = ms => new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout')), ms));
    
    const fetchWithTimeout = (url, timeoutMs) =>
      Promise.race([fetch(url), timeout(timeoutMs)]);
    
    fetchWithTimeout('/api/data', 5000)
      .then(data => console.log('Data:', data))
      .catch(error => console.error('Error:', error));

使用 finally 方法

  • finally 方法:无论 Promise 是否成功或失败,都会执行的回调函数。这在清理资源或执行某些始终需要执行的操作时非常有用。

    typescript 复制代码
    const promise = fetch('/api/data');
    
    promise
      .then(response => response.json())
      .then(data => console.log('Data:', data))
      .catch(error => console.error('Error:', error))
      .finally(() => console.log('Request finished'));

Promise.withResolvers

Promise.withResolvers 通常表示一个可以创建有解析和拒绝能力的 Promise 的方法,这并不是 JavaScript 原生 Promise 的一部分,而是一个用于实现特定功能的自定义方案。

使用场景

  • 处理异步操作的状态管理
  • 协调多个异步操作(并行请求)
  • 事件处理
  • 表单验证
  • 功能开关

错误处理

  • 如果在 Promise 链中的任何一个 .then() 方法中抛出了异常,这个异常会被传递给下一个 .catch() 方法。
  • 如果没有 .catch() 方法,异常将被当作未捕获的异常处理,可能会导致程序崩溃。

注意事项

  • 不可取消:一旦创建了 Promise,就无法取消它。
  • 忽略错误 :如果没有为 Promise 设置 .catch() 回调,那么内部抛出的错误将被忽略。
  • 多次调用 :对同一个 Promise 调用多次 .then().catch() 是安全的,每个回调都会被调用一次。

实现原理

  • Promise 的实现基于事件循环机制,当异步操作完成时,会将相应的回调函数放入微任务队列中,等待当前任务执行完毕后执行这些回调函数。
  • Promise 的状态转换是单向的 ,从 pendingfulfilledrejected,且状态一旦改变就不能再变。
相关推荐
腾讯TNTWeb前端团队23 分钟前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰4 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪4 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪4 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy5 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom5 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom5 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom5 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom6 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom6 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试