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,且状态一旦改变就不能再变。
相关推荐
CherishTaoTao2 分钟前
Vue3 keep-alive核心源码的解析
前端·vue3
关爱的眼神63720 分钟前
html练习2
前端·css·html
laocooon52385788632 分钟前
代码之玫瑰。C++
前端·算法
小牛itbull44 分钟前
ReactPress—基于React的免费开源博客&CMS内容管理系统
前端·react.js·开源·reactpress
GDAL1 小时前
npm入门教程13:npm workspace功能
前端·npm·node.js
呼叫69451 小时前
为什么说vue是双向数据流
前端·javascript·vue.js
我命由我123452 小时前
CesiumJS 案例 P20:监听鼠标滚轮、监听鼠标左键按下与松开、监听鼠标右键按下与松开、监听鼠标左击落点
开发语言·前端·javascript·前端框架·html·css3·html5
wumu_Love2 小时前
npm 和 node 总结
前端·npm·node.js
顾辰呀2 小时前
css 文字一行没有放满不进行换行
前端·javascript·css·vue.js·css3
q567315232 小时前
Python 中的字符串匹配算法
android·java·javascript·python·算法