首页/文章/javascript

Promise 从原理到实现

2025-08-04
5942 分钟
...

前言

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

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

正文

一、Promise 基础概念

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

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

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

二、Promise 核心静态方法实现

1. Promise.resolve 实现

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

Promise.resolve = (param) => {
  if(param instanceof Promise) return param;
  return new Promise((resolve, reject) => {
    if(param && param.then && typeof param.then === 'function') {
      
      param.then(resolve, reject);
    }else {
      resolve(param);
    }
  })
}

实现要点:

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

2. Promise.reject 实现

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

Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
        reject(reason);
    });
}

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

三、Promise 实例方法实现

1. Promise.prototype.finally 实现

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

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

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);
        }
      });
    }));
  }
  
  
}

四、Promise 高级静态方法实现

1. Promise.all 实现

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

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 的结果。

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 完成无论成功或失败

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+ 规范的完整实现:

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);
  }
}


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 的核心在于状态管理链式调用异步处理

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
javascript2025-09-18
JavaScript 的多线程能力:Worker
如果你写过一些计算量稍大的 JavaScript 代码,比如图像处理、大量数据排序或者复杂的算法,你几乎肯定遇到过浏览器“卡死”的现象。点击页面没反应,动画也停了,就像整个世界都静止了。 这就是主线程被阻塞的典型后果。因为主线程既要负责执行 JavaScript,又要负责渲染页面、响应用户操作,一旦它被繁重的计算任务占满,就无暇顾及其他,用户体验便直线下降。 这个问题的根源,正是“主线程是单线程的”。那么,如何解决呢? 答案很简单:把这...
学习面试
javascript2025-09-10
手把手教你实现一个EventEmitter
你是不是也遇到过这种情况:代码里各种事件监听和触发,回调函数套了一层又一层,最后自己都理不清哪个事件先触发、哪个后触发了? 别担心,今天我就带你从零开始实现一个自己的事件触发器(EventEmitter),让你彻底掌握事件驱动的精髓,代码清晰度直接提升200%! 为什么要懂EventEmitter? 先说说为什么我们要关心这个。Node.js的核心就是事件驱动,比如文件读写、网络请求,都是通过事件来处理的。不会EventEmitter,...
学习面试
javascript2025-08-09
Web Worker 多线程魔法
你是否曾遇到过网页因为复杂计算而卡顿的情况?今天,让我们一起探索Web Worker的神奇世界,看看如何用多线程技术解决性能瓶颈,并实现流畅的图片压缩功能! 为什么需要Web Worker? 想象一下,你在一个繁忙的餐厅里,只有一位服务员(主线程)负责点餐、上菜、结账所有工作。当客人突然暴增时,这位服务员就会手忙脚乱,其他客人只能干等着… 这就是JavaScript的现状—— 单线程 !所有任务都在一个线程中排队执行,一旦遇到复杂计算(...
学习面试
javascript2025-08-07
🌐AST抽象语法树
AST 是前端开发中一个非常重要的概念,它就像是代码的“编译器”,能够帮助我们理解和操作代码。本文将深入探讨 AST 的原理和应用,带你从零开始了解 AST。 一、什么是 AST? AST(抽象语法树)是一种树形结构,用于表示程序代码的语法结构。它将代码分解为一系列的节点,每个节点代表代码中的一个元素,如变量、函数、表达式等。AST 是编译器和解释器的基础,也是代码分析和转换的关键工具。 1\. AST 的结构 AST 的结构通常包括以...
学习面试
javascript2025-08-05
打字机效果是如何实现的
分析效果 使用 AI 对话的时候,文字是一个字一个字蹦出来的?它不是等所有内容生成完毕后一次性展示,而是以一种流畅、实时的“打字机”效果呈现,这种体验的背后,隐藏着一种高效的Web技术。它就是 服务器推送事件(Server Sent Events,简称 SSE) 什么是 SSE 从根本上说,SSE 是一种允许服务器 单向 、 持续 地向客户端(浏览器)推送数据的Web技术。 可以把它想象成一个 电台广播 : 服务器 是广播电台,持续不断...
学习面试
javascript2025-08-03
Web Worker:让前端飞起来的隐形引擎
在现代 Web 开发中,前端性能优化是一个至关重要的课题,尤其是对于计算密集型的应用,如图像处理、视频处理、大规模数据分析等任务。单线程的 JavaScript 引擎常常成为性能瓶颈,导致应用变得迟缓。 Web Worker ,作为一种强大的技术,使得前端能够在后台进行并行计算,从而实现高效的任务处理,不影响主线程的运行和用户的交互体验。 本文将深入探讨 Web Worker 的概念、工作原理、使用方法以及实际应用场景,帮助你更好地理解...
学习面试

评论

请登录后发表评论

去登录
加载评论中...

目录