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,且状态一旦改变就不能再变。
相关推荐
类人_猿1 小时前
ASP.NET Web(.Net Framework) Http服务器搭建以及IIS站点发布
前端·iis·asp.net·.net·http站点服务器
组态软件4 小时前
web组态软件
前端·后端·物联网·编辑器·html
前端Hardy4 小时前
HTML&CSS:MacBook Air 3D 动画跃然屏上
前端·javascript·css·3d·html
loey_ln5 小时前
观察者模式和发布订阅模式
javascript·观察者模式·react.js
cnsxjean7 小时前
SpringBoot集成Minio实现上传凭证、分片上传、秒传和断点续传
java·前端·spring boot·分布式·后端·中间件·架构
ZL_5677 小时前
uniapp中使用uni-forms实现表单管理,验证表单
前端·javascript·uni-app
沉浮yu大海7 小时前
Vue.js 组件开发:构建可重用且高效的 UI 块
前端·vue.js·ui
代码欢乐豆8 小时前
软件工程第13章小测
服务器·前端·数据库·软件工程
sunly_8 小时前
Flutter:启动屏逻辑处理02:启动页
android·javascript·flutter
EasyNTS8 小时前
H5流媒体播放器EasyPlayer.js网页直播/点播播放器如果H.265视频在播放器上播放不流畅,可以考虑的解决方案
javascript·音视频·h.265