总结一下 Promise,怎么使用,如何手写 promise

Promise 概述

Promise 是 JavaScript 中的一个异步编程解决方案,它代表了一个最终可能完成(或失败)及其结果值的异步操作。Promise 有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。Promise 一旦从 pending 状态变为 fulfilled 或 rejected 状态,状态就不会再改变,即 Promise 的状态是不可逆的。

Promise 的基本使用

1. 创建 Promise

使用 new Promise(executor) 构造函数来创建一个 Promise 实例,executor 函数接受两个参数:resolve 和 reject,它们是两个函数,由 JavaScript 引擎提供,分别用于将 Promise 的状态从 pending 变为 fulfilled 或 rejected。

javascript 复制代码
let promise = new Promise(function(resolve, reject) {
  // 异步操作
  if (/* 异步操作成功 */) {
    resolve(value); // 将 Promise 的状态从 pending 变为 fulfilled,并将结果作为参数传递
  } else {
    reject(error); // 将 Promise 的状态从 pending 变为 rejected,并将错误作为参数传递
  }
});
2. 使用 Promise

Promise 提供了 .then()、.catch() 和 .finally() 方法用于处理异步操作的结果或错误。

  • .then(onFulfilled, onRejected):当 Promise 变为 fulfilled 或 rejected 时,相应的函数会被调用。
  • .catch(onRejected):用于指定发生错误时的回调函数,是 .then(null, onRejected) 的语法糖。
  • .finally(onFinally):无论 Promise 最终状态如何,都会执行该函数。
javascript 复制代码
promise.then(function(value) {
  // 处理成功的情况
}).catch(function(error) {
  // 处理错误的情况
}).finally(function() {
  // 无论成功或失败都会执行
});

手写 Promise

下面是一个简化版的 Promise 实现,主要实现了基本的状态管理和 .then() 方法。

javascript 复制代码
function MyPromise(executor) {
  this.status = 'pending'; // 初始状态
  this.value = undefined; // 存放异步操作的结果
  this.reason = undefined; // 存放错误原因
  this.onFulfilledCallbacks = []; // 存放成功的回调函数
  this.onRejectedCallbacks = []; // 存放失败的回调函数

  // 更改 Promise 的状态
  function resolve(value) {
    if (this.status === 'pending') {
      this.status = 'fulfilled';
      this.value = value;
      this.onFulfilledCallbacks.forEach(fn => fn());
    }
  }

  function reject(reason) {
    if (this.status === 'pending') {
      this.status = 'rejected';
      this.reason = reason;
      this.onRejectedCallbacks.forEach(fn => fn());
    }
  }

  // 捕获 executor 执行器中的错误
  try {
    executor(resolve.bind(this), reject.bind(this));
  } catch (e) {
    reject.call(this, e);
  }

  // 实现 then 方法
  MyPromise.prototype.then = function(onFulfilled, onRejected) {
    onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value;
    onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason; };

    return new MyPromise((resolve, reject) => {
      if (this.status === 'fulfilled') {
        setTimeout(() => {
          try {
            let x = onFulfilled(this.value);
            resolvePromise(resolve, reject, x);
          } catch (e) {
            reject(e);
          }
        });
      } else if (this.status === 'rejected') {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason);
            resolvePromise(resolve, reject, x);
          } catch (e) {
            reject(e);
          }
        });
      } else {
        this.onFulfilledCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value);
              resolvePromise(resolve, reject, x);
            } catch (e) {
              reject(e);
            }
          });
        });

        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(resolve, reject, x);
            } catch (e) {
              reject(e);
            }
          });
        });
      }
    });
  };

  // 辅助函数,处理 then 或 catch 中的返回值
  function resolvePromise(resolve, reject, x) {
    // ... 省略了一些复杂的处理逻辑,如处理 x 为 Promise 的情况
    if (x !== promise2) { // 避免自引用
      if (x instanceof MyPromise) {
        x.then(resolve, reject);
      } else {
        resolve(x);
      }
    }
  }
}

注意:上面的代码是一个非常简化的版本,省略了很多重要的细节和错误处理逻辑(比如处理 x 为 Promise 的情况),以及 .catch() 和 .finally() 方法的实现。在实际应用中,Promise 的实现要复杂得多,并且需要处理各种边界情况和错误。

相关推荐
广州华水科技7 分钟前
北斗形变监测传感器在大坝安全监测中的应用与优势分析
前端
孔令飞13 分钟前
如何学习Go
前端
HUIBUR科技17 分钟前
AI 中枢,面向企业场景构建的 AI 智能体
前端·数据库·人工智能
怕浪猫24 分钟前
给AI配一台电脑,开源版Muse来了,OpenMuse赶紧去二次开发吧
javascript·面试·github
随便写个软件34 分钟前
【新版本】EasyExplorer资源管理器 3.12.0——地址栏重要更新
运维·服务器·前端·everything·资源管理器
Jack N37 分钟前
【Strapi 系列之二】Collection / Single / Component 怎么选?Strapi 字段大全一篇讲透
前端·javascript·strapi
hiahiahia1231 小时前
Agent Tool 执行失败怎么办
服务器·前端
Java后端的Ai之路1 小时前
09-React组件生命周期
前端·react.js·前端框架
IT_陈寒1 小时前
SpringBoot开发实战:从入门到精通
前端·人工智能·后端
乘风gg1 小时前
一个人一个月合并 2500 PRs 的秘密是什么?
前端·ai编程·claude