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

Promise 概述

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

Promise 的基本使用

1. 创建 Promise

使用 new Promise(executor) 构造函数来创建一个 Promise 实例,executor 函数接受两个参数:resolvereject,它们是两个函数,由 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 的实现要复杂得多,并且需要处理各种边界情况和错误。

相关推荐
baiduopenmap7 分钟前
百度世界2024精选公开课:基于地图智能体的导航出行AI应用创新实践
前端·人工智能·百度地图
loooseFish15 分钟前
小程序webview我爱死你了 小程序webview和H5通讯
前端
小牛itbull18 分钟前
ReactPress vs VuePress vs WordPress
开发语言·javascript·reactpress
请叫我欧皇i27 分钟前
html本地离线引入vant和vue2(详细步骤)
开发语言·前端·javascript
533_30 分钟前
[vue] 深拷贝 lodash cloneDeep
前端·javascript·vue.js
guokanglun35 分钟前
空间数据存储格式GeoJSON
前端
GIS瞧葩菜39 分钟前
局部修改3dtiles子模型的位置。
开发语言·javascript·ecmascript
zhang-zan1 小时前
nodejs操作selenium-webdriver
前端·javascript·selenium
ZBY520311 小时前
【Vue】 npm install amap-js-api-loader指南
javascript·vue.js·npm
猫爪笔记1 小时前
前端:HTML (学习笔记)【2】
前端·笔记·学习·html