前端开发,Promise 从原理到实现,一文通

前言

Promisejs 异步编程的核心概念之一,它为我们提供了一种更优雅的方式来处理异步操作。

本文将全面剖析 Promise 的工作原理,并逐步实现一个符合 Promise/A+ 规范的 Promise 库

正文

一、Promise 基础概念

Promise 代表一个异步操作的最终完成(或失败)及其结果值。它有种状态:

  1. pending初始状态,既不是成功,也不是失败状态
  2. fulfilled :意味着操作成功完成
  3. rejected :意味着操作失败

状态一旦改变就不能再变,只能从 pending 变为 fulfilled ,或从 pending 变为 rejected

二、Promise 核心静态方法实现

1. Promise.resolve 实现

Promise.resolve 方法返回一个以给定值解析后的 Promise 对象

javascript 复制代码
Promise.resolve = (param) => {
  if(param instanceof Promise) return param;
  return new Promise((resolve, reject) => {
    if(param && param.then && typeof param.then === 'function') {
      // param 状态变为成功会调用resolve,将新 Promise 的状态变为成功,反之亦然
      param.then(resolve, reject);
    }else {
      resolve(param);
    }
  })
}

实现要点:

  • 如果参数Promise 实例,直接返回该实例
  • 如果参数是 thenable 对象(具有 then 方法的对象),返回的 Promise 会跟随这个对象`
  • 其他情况返回一个以该值为成功状态的 Promise 对象

2. Promise.reject 实现

Promise.reject 方法返回一个带有拒绝原因Promise 对象

javascript 复制代码
Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
        reject(reason);
    });
}

与 resolve 不同,reject 会原封不动地将 reason 向下传递

三、Promise 实例方法实现

1. Promise.prototype.finally 实现

finally 方法无论 Promise 最终状态如何都会执行。

javascript 复制代码
Promise.prototype.finally = function(callback) {
  this.then(value => {
    return Promise.resolve(callback()).then(() => {
      return value;
    })
  }, error => {
    return Promise.resolve(callback()).then(() => {
      throw error;
    })
  })
}

实现要点:

  • 无论成功或失败都会执行回调
  • 保持原 Promise下传
  • 回调函数返回的 Promise 会等待执行完毕

2. Promise.prototype.then 实现

then 方法是 Promise 的核心,它返回一个新的 Promise

javascript 复制代码
MyPromise.prototype.then = function (onResolved, onRejected) {
  var self = this;
  var promise2;
  
  // onResolved 和 onRejected 都是可选的
  onResolved = typeof onResolved === 'function' ? onResolved : v => v;
  onRejected = typeof onRejected === 'function' ? onRejected : r => { throw r };

  if (self.currentState === RESOLVED) {
    return (promise2 = new MyPromise(function (resolve, reject) {
      setTimeout(function () {
        try {
          var x = onResolved(self.value);
          resolutionProcedure(promise2, x, resolve, reject);
        } catch (reason) {
          reject(reason);
        }
      });
    }));
  }
  
  // 其他状态类似处理...
}

四、Promise 高级静态方法实现

1. Promise.all 实现

Promise.all 接收一个 Promise 数组,当所有 Promise 都成功时返回结果数组,有一个失败则立即失败

javascript 复制代码
Promise.all = function(promises) {
  return new Promise((resolve, reject) => {
    let result = [];
    let index = 0;
    let len = promises.length;
    if(len === 0) {
      resolve(result);
      return;
    }

    for(let i = 0; i < len; i++) {
      Promise.resolve(promises[i]).then(data => {
        result[i] = data;
        index++;
        if(index === len) resolve(result);
      }).catch(err => {
        reject(err);
      })
    }
  })
}

2. Promise.race 实现

Promise.race 返回第一个完成的 Promise 的结果。

javascript 复制代码
Promise.race = function(promises) {
  return new Promise((resolve, reject) => {
    let len = promises.length;
    if(len === 0) return;
    for(let i = 0; i < len; i++) {
      Promise.resolve(promises[i]).then(data => {
        resolve(data);
        return;
      }).catch(err => {
        reject(err);
        return;
      })
    }
  })
}

3. Promise.allSettled 实现

Promise.allSettled 等待所有 Promise 完成无论成功或失败

javascript 复制代码
function allSettled(iterable) {
  return new Promise((resolve, reject) => {
    function addElementToResult(i, elem) {
      result[i] = elem;
      elementCount++;
      if (elementCount === result.length) {
        resolve(result);
      }
    }

    let index = 0;
    for (const promise of iterable) {
      const currentIndex = index;
      promise.then(
        (value) => addElementToResult(
          currentIndex, {
            status: 'fulfilled',
            value
          }),
        (reason) => addElementToResult(
          currentIndex, {
            status: 'rejected',
            reason
          }));
      index++;
    }
    if (index === 0) {
      resolve([]);
      return;
    }
    let elementCount = 0;
    const result = new Array(index);
  });
}

代码:完整 Promise 实现

下面是一个符合 Promise/A+ 规范的完整实现:

javascript 复制代码
// 三种状态
const PENDING = "pending";
const RESOLVED = "resolved";
const REJECTED = "rejected";

function MyPromise(fn) {
  let _this = this;
  _this.currentState = PENDING;
  _this.value = undefined;
  _this.resolvedCallbacks = [];
  _this.rejectedCallbacks = [];

  _this.resolve = function (value) {
    if (value instanceof MyPromise) {
      return value.then(_this.resolve, _this.reject)
    }
    setTimeout(() => {
      if (_this.currentState === PENDING) {
        _this.currentState = RESOLVED;
        _this.value = value;
        _this.resolvedCallbacks.forEach(cb => cb());
      }
    })
  };

  _this.reject = function (reason) {
    setTimeout(() => {
      if (_this.currentState === PENDING) {
        _this.currentState = REJECTED;
        _this.value = reason;
        _this.rejectedCallbacks.forEach(cb => cb());
      }
    })
  }
  
  try {
    fn(_this.resolve, _this.reject);
  } catch (e) {
    _this.reject(e);
  }
}

// then 方法实现
MyPromise.prototype.then = function (onResolved, onRejected) {
  var self = this;
  var promise2;
  
  onResolved = typeof onResolved === 'function' ? onResolved : v => v;
  onRejected = typeof onRejected === 'function' ? onRejected : r => { throw r };

  if (self.currentState === RESOLVED) {
    return (promise2 = new MyPromise(function (resolve, reject) {
      setTimeout(function () {
        try {
          var x = onResolved(self.value);
          resolutionProcedure(promise2, x, resolve, reject);
        } catch (reason) {
          reject(reason);
        }
      });
    }));
  }
  
  // 其他状态处理...
};

// 解析过程
function resolutionProcedure(promise2, x, resolve, reject) {
  if (promise2 === x) {
    return reject(new TypeError("Error"));
  }
  
  if (x instanceof MyPromise) {
    if (x.currentState === PENDING) {
      x.then(function (value) {
        resolutionProcedure(promise2, value, resolve, reject);
      }, reject);
    } else {
      x.then(resolve, reject);
    }
    return;
  }
  
  let called = false;
  if (x !== null && (typeof x === "object" || typeof x === "function")) {
    try {
      let then = x.then;
      if (typeof then === "function") {
        then.call(
          x,
          y => {
            if (called) return;
            called = true;
            resolutionProcedure(promise2, y, resolve, reject);
          },
          e => {
            if (called) return;
            called = true;
            reject(e);
          }
        );
      } else {
        resolve(x);
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e);
    }
  } else {
    resolve(x);
  }
}
  1. 状态管理:Promise 的状态一旦改变就不能再变
  2. 异步执行:then 方法的回调需要异步执行
  3. 链式调用:then 方法必须返回一个新的 Promise
  4. 值穿透:then 的参数如果不是函数需要忽略
  5. Promise 解析过程:处理 thenable 对象和循环引用

总结

Promise 的核心在于状态管理链式调用异步处理

了解其底层原理,将使我们能够更好地使用和调试Promise代码,去运用一些第三方Promise库。

相关推荐
90后的晨仔24 分钟前
在macOS上无缝整合:为Claude Code配置魔搭社区免费API完全指南
前端
沿着路走到底1 小时前
JS事件循环
java·前端·javascript
子春一21 小时前
Flutter 2025 可访问性(Accessibility)工程体系:从合规达标到包容设计,打造人人可用的数字产品
前端·javascript·flutter
白兰地空瓶1 小时前
别再只会调 API 了!LangChain.js 才是前端 AI 工程化的真正起点
前端·langchain
jlspcsdn2 小时前
20251222项目练习
前端·javascript·html
行走的陀螺仪3 小时前
Sass 详细指南
前端·css·rust·sass
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ3 小时前
React 怎么区分导入的是组件还是函数,或者是对象
前端·react.js·前端框架
LYFlied3 小时前
【每日算法】LeetCode 136. 只出现一次的数字
前端·算法·leetcode·面试·职场和发展
子春一23 小时前
Flutter 2025 国际化与本地化工程体系:从多语言支持到文化适配,打造真正全球化的应用
前端·flutter
QT 小鲜肉3 小时前
【Linux命令大全】001.文件管理之file命令(实操篇)
linux·运维·前端·网络·chrome·笔记