promise自定义封装(手写promise)源码

152 阅读21分钟

一、基本框架实现

实现以下结构的promise自定义封装

<script>
const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('oK');
    }, 1000);
})
.then((value) => {
    console.log(value);
})
.catch((reason) => {
    console.log(reason);
});

</script>

步骤:

1. 初始结构状态搭建

2. resolve与reject结构搭建

3. throw抛出异常状态改变

4. promise对象状态只修改一次

5. then方法执行回调

<script>
//1.构造函数
function Promise(executor){
    //添加属性
    //设置初始状态
    this.Promisestate ='pending'
    //设置初始值
    this.PromiseResult = null
    //保存实例对象的this值
    const self = this
    //2. resolve与reject结构搭建
    function resolve(data){
        //判断  4. promise对象状态只修改一次
        if(self.PromiseState !== 'pending')return
        //(1)修改对象状态(Promisestate)
        self.Promisestate='fulfilled'//resolved 解决
        //(2)设置对象结果值(PromiseResult)
        self.PromiseResult = data
    }
    function reject(data){
        //判断  4. promise对象状态只修改一次
        if(self.PromiseState !== 'pending')return
        //(1)修改对象状态(Promisestate)
        self.PromiseState="rejected"
        //(2)设置对象结果值(PromiseResult)
        self.PromiseResult=data
    }
    //3. throw抛出异常状态改变
    try {
        //同步调用[执行器函数]
        executor(resolve,reject)
    }catch(e){
        //修改promise对象状态为失败
        reject(e)
    }
}

//5.添加then方法 (then方法执行回调)
Promise.prototype.then=function(onResolve, onReject){
    //调用回调函数 Promisestate
    if(this.PromiseState ==='fulfilled'){
        onResolve(this.PromiseResult)
     }
    if(this.PromiseState ==='rejected'){
        onReject(this.PromiseResult)
     }
 }
</script>

6.同步异步回调处理时机

1. 同步修改状态(状态已确定)

if (this.PromiseState === 'fulfilled') {
  onResolve(this.PromiseResult) // 直接调用成功回调
}
if (this.PromiseState === 'rejected') {
  onReject(this.PromiseResult) // 直接调用失败回调
}
  • 原因
    当 then 被调用时,Promise 的状态已经同步确定(例如在构造函数中直接调用了 resolve/reject)。

  • 行为
    可以立即使用已知的 PromiseResult 调用对应的回调函数(onResolve 或 onReject)。

  • 示例

    const p = new MyPromise((resolve) => resolve(123))
    p.then(res => console.log(res)) // 同步执行,立即输出 123
    

2. 异步修改状态(状态未确定)

if (this.PromiseState === 'pending') {
  this.callbacks.push({ // 保存回调到数组
    onResolve: () => onResolve(this.PromiseResult),
    onReject: () => onReject(this.PromiseResult)
  })
}
  • 原因
    当 then 被调用时,Promise 的状态尚未确定(例如 resolve/reject 在 setTimeout 中异步调用)。

  • 行为
    无法立即执行回调,必须先将回调函数保存起来,等待未来状态确定后再触发。

  • 示例

    const p = new MyPromise((resolve) => {
      setTimeout(() => resolve(123), 1000)
    })
    p.then(res => console.log(res)) // 1秒后异步执行
    

关键区别:回调的执行时机

场景状态时机then 的行为必要性
同步修改调用 then 前已确定立即执行回调结果立即可用
异步修改调用 then 时未确定保存回调,延迟执行结果未来才可用

举个例子:

  • 同步
const p = new Promise((resolve, reject) => {
  resolve('success'); // 同步调用 resolve
});

p.then(
  value => console.log(value), // onResolve
  reason => console.error(reason) // onReject
);

阶段1:同步代码执行(调用栈)

  1. 创建 Promise 实例 p

    • 同步执行 executor 函数 (resolve, reject) => { ... }

    • 立即调用 resolve('success')

    • 此时 Promise 内部状态变为:

      {
        PromiseState: 'fulfilled',
        PromiseResult: 'success'
      }
      
  2. 调用 p.then() 方法

    • 检查 p 的状态已经是 fulfilled

    • 将 onResolve 回调(value => console.log(value))放入微任务队列

    • 此时微任务队列内容:

      [微任务1: console.log('success')]
      

阶段2:微任务执行(当前宏任务结束后)

  1. 事件循环处理微任务队列

    • 从微任务队列中取出并执行 onResolve 回调
    • 执行 console.log('success')
    • 控制台输出:success
  2. 微任务队列清空

    • 所有微任务执行完毕,程序结束

关键机制说明

  1. Promise 状态变化是同步的

    resolve('success'); // 同步修改状态
    
    • 此操作会立即将 Promise 从 pending 变为 fulfilled
    • 但回调函数(.then)的执行永远是异步的(即使状态已确定)
  2. .then() 的回调调度规则

    • 如果 Promise 已经是 fulfilled/rejected

      • 将对应的回调(onResolve 或 onReject放入微任务队列
    • 如果 Promise 还是 pending

      • 将回调暂存,待状态变化后再调度

image.png

  • 异步
const p = new Promise((resolve, reject) => {
    setTimeout(() => resolve('success'), 1000)
})

p.then(
    value => console.log(value), // onResolve
    reason => console.error(reason) // onReject
)

image.png

二、异步任务回调的执行

setTimeout模拟异步任务回调

<script>
const p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('oK');
    }, 1000);
})
.then((value) => {
    console.log(value);
})
.catch((reason) => {
    console.log(reason);
});

</script>
  1. 在状态改变之前先保存回调函数,注意先声明callback属性
this.callback={}
//添加then方法 (then方法执行回调)
Promise.prototype.then=function(onResolve, onReject){
    //调用回调函数 Promisestate
    if(this.PromiseState ==='fulfilled'){
        onResolve(this.PromiseResult)
     }
    if(this.PromiseState ==='rejected'){
        onReject(this.PromiseResult)
     }
     // 在状态改变之前先保存回调函数,注意先声明callback属性
    if (this.PromiseState === 'pending') {
     this.callback = {
       onResolve: onResolve,
       onReject: onReject
    },
 }

  1. 调用成功/失败时的回调函数
//声明属性     
this.callback = {}
  //resolve函数  
    function resolve(data) {  
        //判断  
        if (self.PromiseState !== 'pending'return  
        //1.修改对象状态(PromiseState)  
        self.PromiseState = 'fulfilled'//resolved 解决  
        //2.设置对象结果值(PromiseResult)  
        self.PromiseResult = data  
        //调用成功的回调函数  
        //如果self.callback里面有onResolve  
         if (self.callback.onResolve) {  
             self.callback.onResolve(data)  
         }  
       
    }
    //reject函数  
    function reject(data) {  
        //判断  
        if (self.PromiseState !== 'pending'return  
        //1.修改对象状态(PromiseState)  
        self.PromiseState = 'rejected'  
        //2.设置对象结果值(PromiseResult)  
        self.PromiseResult = data  
        //调用失败的回调函数  
        //如果self.callback里面有onRejected  
         if (self.callback.onReject) {  
             self.callback.onReject(data)  
         }  
    }

三、指定多个回调的实现

//异步任务回调执行
const p =new Promise((resolve, reject)=>{
    setTimeout(()=>{resolve('ok')},1000)
    // reject('err')
    // throw('err')
})

//指定多个回调
p.then((value)=>{
    console.log(value)
},(reason)=>{
console.warn(reason)
})

p.then((value)=>{
    alert(value)
},(reason)=>{
    alert(reason)
})

指定多个回调,this.callback = { onResolve: onResolve, onReject: onReject }这种写法就会使后面的对象覆盖前面的,只会执行alert;

企业微信截图_17149673203975.png

解决办法,把多个回调函数存在数组里;

// 构造函数中初始化数组
this.callbacks = []; 

// then方法中
this.callbacks.push({ 
  onResolve: onResolve,
  onReject: onReject
});

1. 为什么 this.callback = { ... } 是错误的?

this.callback = { 
  onResolve: onResolve,
  onReject: onReject
}
  • 问题:每次调用 .then() 都会覆盖之前的回调。
    例如:

    promise.then(callback1); 
    promise.then(callback2); // 覆盖 callback1,只保留 callback2
    
  • 后果:当 Promise 状态变为 fulfilled/rejected 时,只有最后一次设置的回调会被执行,违反了 Promise/A+ 规范(要求保留所有回调)。


2. 为什么 this.callbacks.push({ ... }) 是正确的?

// 构造函数中初始化数组
this.callbacks = []; 

// then方法中
this.callbacks.push({ 
  onResolve: onResolve,
  onReject: onReject
});
  • 原因

    • 同一个 Promise 可能多次调用 .then()(如 promise.then(f1); promise.then(f2);)。
    • 需要用数组存储所有回调,确保后续状态变化时按顺序执行所有回调
    • 符合 Promise/A+ 规范(2.2.6:then 可能被多次调用,需按注册顺序执行回调)。

修改callback定义,且利用forEach遍历数组对象

按顺序执行所有回调

//声明属性     
this.callback = {}
  //resolve函数  
    function resolve(data) {  
        //判断  
        if (self.PromiseState !== 'pending'return  
        //1.修改对象状态(PromiseState)  
        self.PromiseState = 'fulfilled'//resolved 解决  
        //2.设置对象结果值(PromiseResult)  
        self.PromiseResult = data  
        //调用成功的回调函数  
       //如果self.callback里面有onResolve  
        // if (self.callback.onResolve) {  
        //     self.callback.onResolve(data)  
        // }  
        setTimeout(() => {  
            self.callback.forEach(item => {  
                item.onResolve(data)  
            })  
        })  
       
    }
    //reject函数  
    function reject(data) {  
        //判断  
        if (self.PromiseState !== 'pending'return  
        //1.修改对象状态(PromiseState)  
        self.PromiseState = 'rejected'  
        //2.设置对象结果值(PromiseResult)  
        self.PromiseResult = data  
        //调用失败的回调函数  
        //如果self.callback里面有onReject  
        // if (self.callback.onReject) {  
        //     self.callback.onReject(data)  
        // }  
        setTimeout(() => {  
            self.callback.forEach(item => {  
                item.onReject(data)  
            })  
        })  
    }

image.png

四、同步修改状态then方法结果返回

image.png

结果:

image.png

(因为上述回调函数没有加return,所以PromiseResult为undifined)

同理reject状态执行结果: image.png 关键:如果.then后面的函数返回的是非promise状态的函数,比如undifine,字符串等,状态都是resolve状态的;如果返回的是promise状态的,这个返回的promise状态就决定了.then结果的状态

实现源码:

//添加then方法 (then方法执行回调)
Promise.prototype.then=function(onResolve, onReject){
    //调用回调函数 Promisestate
    if(this.PromiseState ==='fulfilled'){
        onResolve(this.PromiseResult)
     }
    if(this.PromiseState ==='rejected'){
        onReject(this.PromiseResult)
     }
     // 在状态改变之前先保存回调函数,注意先声明callback属性
    if (this.PromiseState === 'pending') {
     this.callback.push({
       onResolve: onResolve,
       onReject: onReject
    }),
 }

then方法返回结果:

  1. 非promise对象的reslove;
  2. promise对象的resolve和reject;
  3. 抛出异常情况下,改变状态为失败的reject;

image.png

抛出异常情况

image.png

五、异步修改状态then方法结果返回

image.png

image.png

此时状态还是pending,但是这里正确的Promise的then方法返回的应该是

image.png

修改异步情况下then返回的状态结果在PromiseState===pending

image.png 同时,onReject执行过程同理: then方法返回结果:

  1. 非promise对象的reslove;
  2. promise对象的resolve和reject;
  3. 抛出异常情况下,改变状态为失败的reject;

image.png

代码优化

image.png


疑惑点

异步场景执行流程(状态为 pending)

  1. 初始化阶段
const p = new Promise((resolve) => {
  setTimeout(() => resolve('success'), 1000); // 异步 resolve
});

p.then(value => console.log(value)); // 调用 then 时状态为 pending

2. .then() 方法执行(状态为 pending)

Promise.prototype.then = function (onResolve, onReject) {
  // ...
  if (this.PromiseState === 'pending') {
    // ✅ 进入此分支
    this.callback.push({ 
      onResolve: function () { callback(onResolve) },
      onReject: function () { callback(onReject) }
    })
  }
}
  • 将回调包装后存入 this.callback 数组
  • 不执行任何回调,直接返回新 Promise
  1. 异步操作完成后调用 resolve('success')
function resolve(data) {
  // ...
  self.PromiseState = 'fulfilled'
  self.PromiseResult = data
  setTimeout(() => { // ✅ 关键执行点
    self.callback.forEach(item => {
      item.onResolve(data) // 执行之前存储的回调
    })
  })
}
  • 触发回调执行:通过 setTimeout 调度
  • 遍历存储的回调:执行每个 item.onResolve(data)
  1. 执行回调链

当 item.onResolve(data) 执行时:

// 实际执行的是 .then() 中存储的:
function() { callback(onResolve) }

// 展开 callback 函数:
function callback(type) {
  try {
    let result = type(self.PromiseResult) // 执行用户回调 value => console.log(value)
    // 处理返回值,决定链式调用的状态...
  } catch (e) {
    reject(e)
  }
}

所以在异步执行回调的场景中,当 .then() 被调用时 Promise 状态为 pending执行的是 resolve 函数中的 setTimeout 回调,而不是 .then() 方法中的 if (this.PromiseState === 'fulfilled') 分支。

image.png

六、catch方法-异常穿透和值传递

image.png

异常穿透

异常穿透是 Promise 链式调用中的一个重要特性,它允许错误沿着 Promise 链自动向后传递,直到被捕获处理。

image.png

实现异常穿透的关键代码

// 实现异常穿透的关键:提供默认错误处理
    const defaultOnReject = reason => {
      throw reason; // 抛出错误,使新 Promise 变为 rejected
    };
    
    onReject = typeof onReject === 'function' 
      ? onReject 
      : defaultOnReject;
    
    // 处理 onResolve 的默认行为
    onResolve = typeof onResolve === 'function' 
      ? onResolve 
      : value => value;

异常穿透的工作原理

  1. 默认错误处理行为

异常穿透的核心在于 then 方法的错误处理参数 onReject 的默认行为:

const defaultOnReject = reason => {
  throw reason; // 关键:重新抛出错误
};

当用户没有提供 onReject 处理函数时,我们使用这个默认函数。这个函数简单地重新抛出接收到的错误原因,使新创建的 Promise 状态变为 rejected,并将错误继续传递下去。

  1. 同步错误捕获
try {
  const result = callback(value);
  // ...处理结果
} catch (error) {
  reject(error); // 将同步错误转换为 Promise 拒绝
}

这样即使回调函数中抛出同步错误,也会被捕获并转换为 Promise 的拒绝状态,继续在链中传递。

异常穿透示例

// 创建初始 rejected Promise
const p = new MyPromise((resolve, reject) => {
  reject('Initial error');
});

p.then(result => {
  // 不会执行,因为初始状态是 rejected
  console.log('Success:', result);
})
.then(() => {
  // 没有提供错误处理,错误继续传递
  console.log('This will not execute');
})
.catch(error => {
  // 捕获到穿透传递的错误
  console.log('Caught error:', error); // 输出: Caught error: Initial error
  return 'Recovered';
})
.then(result => {
  // 恢复执行
  console.log('Recovery result:', result); // 输出: Recovery result: Recovered
});

值传递及错误捕获

image.png

执行过程分析

阶段1:同步代码执行(立即执行)

  1. 创建 Promise 对象 p,立即执行 executor 函数:

    • 设置一个定时器(1秒后触发 resolve('ok')
    • 注意reject('err') 和 throw('fail') 被注释掉了
    • 此时 Promise 状态为 pending
  2. 链式调用 .then() 和 .catch()

    • 由于 Promise 还是 pending 状态,所有回调都被暂存到微任务队列

    • 此时回调队列情况:

      微任务队列:
      [then1, then2, then3, catch]
      

阶段2:异步任务执行(1秒后)

  1. 1秒后定时器触发,执行 resolve('ok')

    • Promise 状态从 pending 变为 fulfilled,结果为 'ok'

    • 触发:将第一个 .then() 的回调放入微任务队列

    • 此时微任务队列:

      [then1的回调, then2, then3, catch]
      
  2. 事件循环开始处理微任务队列:

    • 执行第一个 .then() 的回调:

      console.log(111) // 输出: 111
      
      • 回调没有返回值,相当于返回 undefined

      • 创建一个新的 fulfilled 状态的 Promise,值为 undefined

      • 触发:将第二个 .then() 的回调放入微任务队列

      • 微任务队列:

        [then2的回调, then3, catch]
        
    • 执行第二个 .then() 的回调:

      console.log(222) // 输出: 222
      
      • 同样返回 undefined

      • 创建新的 fulfilled Promise

      • 触发:将第三个 .then() 的回调放入微任务队列

      • 微任务队列:

        [then3的回调, catch]
        
    • 执行第三个 .then() 的回调:

      console.log(333) // 输出: 333
      
      • 返回 undefined
      • 创建新的 fulfilled Promise
      • .catch() 不会被调用,因为前面没有 rejection

最终输出顺序

111
222
333

关键点说明

  1. 执行顺序

    • 所有 .then() 注册时都是同步执行的
    • 实际回调要等到 Promise 状态确定后才执行

image.png

  1. 错误情况对比

    • 如果使用 reject('err')

      • 输出:err(catch 捕获)
      • 不会执行任何 .then()
    • 如果使用 throw('fail')

      • 同步抛出异常,Promise 直接变为 rejected
      • 输出:fail(catch 捕获)

image.png

1.异常穿透

场景:

const p = new Promise((resolve, reject) => {
  setTimeout(() => { reject('err') }, 1000)
  // resolve('ok')
  // throw('fail')
})

p.then(value => { console.log(111) })
 .then(value => { console.log(222) })
 .then(value => { console.log(333) })
 .catch(reason => { console.warn(reason) })

封装:

Promise.prototype.then=function(onResolve, onReject){
    const self=this
    if (typeof onReject !== 'function') {
        onReject = reason => { throw reason } // 关键点:重新抛出错误
    }
    if (typeof onResolve !== 'function') {
        onResolve = value => value // 值穿透:直接传递值
    }
}

代码解析:

if (typeof onReject !== 'function') {
    onReject = reason => { throw reason }
}
  • 检查是否提供了错误处理函数 onReject

  • 如果没有提供(即 onReject 不是函数类型):

    • 创建一个默认的错误处理函数
    • 该函数会重新抛出接收到的错误原因

作用:实现异常穿透

Promise.reject('error')
  .then() // 没有提供错误处理
  .then() // 没有提供错误处理
  .catch(console.log) // 最终被捕获
// 输出: 'error'

执行流程

  1. 初始 Promise 被拒绝
  2. 第一个 .then() 没有错误处理 → 执行默认函数 throw reason
  3. 导致返回的新 Promise 也被拒绝(携带相同错误)
  4. 错误继续向下传递,直到被 .catch() 捕获

2.值传递

场景:

const p = new Promise((resolve, reject) => {
  setTimeout(() => { resolve('ok') }, 1000)
  // reject('err')
  // throw('fail')
})

p.then(value => { console.log(111) })
 .then(value => { console.log(222) })
 .then(value => { console.log(333) })
 .catch(reason => { console.warn(reason) })

封装:

Promise.prototype.then=function(onResolve, onReject){
    const self=this
    if (typeof onReject !== 'function') {
        onReject = reason => { throw reason } // 关键点:重新抛出错误
    }
    if (typeof onResolve !== 'function') {
        onResolve = value => value // 值穿透:直接传递值
    }
}

代码解析

if (typeof onResolve !== 'function') {
    onResolve = value => value
}
  • 检查是否提供了成功回调 onResolve

  • 如果没有提供(即 onResolve 不是函数类型):

    • 创建一个默认的成功处理函数
    • 该函数会直接返回接收到的值

作用:实现值穿透

Promise.resolve('success')
  .then() // 没有提供成功回调
  .then(value => console.log(value)) 
// 输出: 'success'

执行流程

  1. 初始 Promise 成功解决
  2. 第一个 .then() 没有成功回调 → 执行默认函数 value => value
  3. 返回的新 Promise 以相同值解决
  4. 值传递给下一个 .then() 被处理
特性条件判断默认行为作用
异常穿透typeof onReject !== 'function'reason => { throw reason }错误沿 Promise 链向下传递
值穿透typeof onResolve !== 'function'value => value值沿 Promise 链向下传递

image.png

七、Promise.resolve封装

1.基本概念

Promise.resolve() 是 Promise 的一个静态方法,用于创建一个已解决(fulfilled)状态的 Promise 对象。

语法

Promise.resolve(value);

参数

  • value:可以是任何 JavaScript 值,包括:

    • 普通值(数字、字符串、对象等)
    • Promise 对象
    • thenable 对象(具有 then 方法的对象)

返回值

返回一个 Promise 对象,其状态取决于传入的 value 参数:

  • 如果参数是普通值,返回 fulfilled 状态的 Promise
  • 如果参数是 Promise 对象,直接返回该 Promise
  • 如果参数是 thenable 对象,返回的 Promise 会"跟随"这个 thenable 对象

image.png

具体场景分析

  • 场景1:参数是非Promise值
Promise.resolve(42)

执行流程:

  1. 检查 42 不是 Promise 实例
  2. 直接调用 resolve(42)
  3. 返回的 Promise 立即变为 fulfilled 状态,值为 42
  • 场景2:参数是已解决的Promise
const p = Promise.resolve('hello')
Promise.resolve(p)

执行流程:

  1. 检测到 p 是 Promise 实例
  2. 调用 p.then() 等待其解决
  3. 当 p 解决后,用相同结果解决新 Promise
  • 场景3:参数是拒绝的Promise
const p = Promise.reject('error')
Promise.resolve(p).catch(console.log) // 会捕获到'error'

执行流程:

  1. 检测到 p 是 Promise 实例
  2. 调用 p.then() 等待其解决
  3. 当 p 拒绝后,用相同原因拒绝新 Promise

与 new Promise() 的区别

特性Promise.resolve()new Promise()
创建方式静态方法构造函数
初始状态总是已解决pending
输入类型处理智能处理各种类型只接受执行器函数
性能更高效(无额外包装)稍低效

Promise.resolve('直接解析')和Promise.resolve('直接解析').then(...)

特性Promise.resolve('直接解析')Promise.resolve('直接解析').then(...)
返回值直接返回一个 fulfilled 状态的 Promise返回一个新的 pending 状态的 Promise
执行时机同步创建 Promise(立即完成)回调函数异步执行(进入微任务队列)
链式调用仅创建 Promise,不触发回调创建 Promise 并注册回调,形成链式调用
控制台输出无输出异步输出 '直接解析'

示例1:基础行为

// 情况1:仅创建 Promise
const p1 = Promise.resolve('直接解析');
// p1 状态立即变为 fulfilled,但无任何输出

// 情况2:创建 Promise 并链式调用
const p2 = Promise.resolve('直接解析').then(val => console.log(val));
// p2 是 pending 状态,回调进入微任务队列
// 后续会输出: '直接解析'

示例2:执行顺序验证

console.log('开始');

Promise.resolve('直接解析'); // 同步创建,无输出

Promise.resolve('链式解析').then(val => console.log(val)); // 回调进入微任务队列

console.log('结束');

// 输出顺序:
// 开始
// 结束
// 链式解析

3. 关键差异解析

(1) 执行机制

  • Promise.resolve('直接解析')

    • 同步创建一个状态为 fulfilled 的 Promise,值为 '直接解析'
    • 不涉及异步逻辑,不会触发任何回调。
  • .then(val => console.log(val))

    • 在前一个 Promise 的基础上注册回调
    • 回调函数会被异步执行(放入微任务队列)
    • 返回一个新的 Promise 对象(初始状态为 pending

(2) 返回值状态

const a = Promise.resolve('A'); 
console.log(a); // Promise {<fulfilled>: 'A'} (立即完成)

const b = Promise.resolve('B').then(val => console.log(val));
console.log(b); // Promise {<pending>} (等待回调执行)

(3) 链式调用的必要性

  • 如果只需要存储值而不处理,用 Promise.resolve() 即可
  • 如果需要处理值或确保异步执行,必须加 .then()

示例3:执行顺序验证

console.log('start');

Promise.resolve('直接解析').then(val => console.log(val));

Promise.resolve().then(() => console.log('通过 then 解析'));

console.log('end');

// 输出顺序:
// start
// end
// 直接解析
// 通过 then 解析

阶段1:同步代码执行(调用栈)

  1. 执行 console.log('start')

    • 立即输出:start
  2. 执行 Promise.resolve('直接解析')

    • 同步创建一个状态为 fulfilled 的 Promise,值为 '直接解析'
    • 将 .then(val => console.log(val)) 的回调放入微任务队列
    • 当前微任务队列:[回调1]
  3. 执行 Promise.resolve()

    • 同步创建一个状态为 fulfilled 的 Promise,值为 undefined
    • 将 .then(() => console.log('通过 then 解析')) 的回调放入微任务队列
    • 当前微任务队列:[回调1, 回调2]
  4. 执行 console.log('end')

    • 立即输出:end

阶段2:微任务执行(当前宏任务结束后

  1. 清空微任务队列(按照先进先出顺序):

    • 执行回调1val => console.log(val)

      • 输出:直接解析
    • 执行回调2() => console.log('通过 then 解析')

      • 输出:通过 then 解析

image.png

示例4:变体思考

console.log('start');

Promise.resolve().then(() => console.log('通过 then 解析'));
Promise.resolve('直接解析').then(val => console.log(val));

console.log('end');

// 输出顺序:
// start
// end
// 通过 then 解析
// 直接解析

2.封装源码:

image.png (返回的是promise的对象,返回的状态决定Promise.resolve去执行什么状态;返回的是成功,Promise.resolve就是去执行成功,返回的是失败,Promise.resolve就是去执行失败,返回的是非promise对象。就设置状态为成功)

八、Promise.reject封装

1.基本概念

Promise.reject() 是 Promise 的一个静态方法,用于快速创建一个已拒绝(rejected)状态的 Promise 对象。

示例1:基本使用

const p = Promise.reject(new Error('Something went wrong'));

p.catch(error => {
  console.error(error.message); // 输出: "Something went wrong"
});

示例2:非错误对象作为原因

Promise.reject('plain string reason')
  .catch(reason => {
    console.log(reason); // 输出: "plain string reason"
  });

与 Promise.resolve() 的区别

特性Promise.reject()Promise.resolve()
初始状态立即创建 rejected 状态的 Promise立即创建 fulfilled 状态的 Promise
参数处理直接作为拒绝原因会展开 thenable 对象
是否展开 thenable不会展开 thenable 对象会展开 thenable 对象
const thenable = {
  then(resolve, reject) {
    resolve('resolved value');
  }
};

// Promise.resolve 会展开 thenable
Promise.resolve(thenable)
  .then(val => console.log(val)); // 输出: "resolved value"

// Promise.reject 不会展开 thenable
Promise.reject(thenable)
  .catch(val => console.log(val === thenable)); // 输出: true

链式调用中的行为

Promise.reject('first error')
  .then(() => {
    console.log('This will never run');
  })
  .catch(err => {
    console.log('Caught:', err); // 输出: "Caught: first error"
    return 'recovery value';
  })
  .then(val => {
    console.log('After recovery:', val); // 输出: "After recovery: recovery value"
  });

2.封装源码

Promise.rejectPromise.resolve的不同就是,不管传什么参数,都是执行reject

image.png

九、Promise.all封装--全部成功

all 相当于是 & 关系

image.png

image.png

如果有一个失败就是返回失败的那一个的状态

image.png

优化版:

image.png

十、Promise.race封装--竞速

image.png Promise.race的结果由数组中第一个改变的状态的promise决定

image.png image.png

优化版

image.png

十一、Promise.any封装 -- 任意成功

  • 成功条件:任意一个 Promise 成功
  • 失败条件:所有 Promise 都失败
  • 返回值:第一个成功的值 或 AggregateError

image.png

对比总结

特性Promise.all()Promise.race()Promise.any()
成功条件所有成功第一个完成(无论成败)任意一个成功
失败条件任意一个失败无特定条件所有失败
返回值结果数组(按顺序)第一个完成的值第一个成功的值
空输入解决(空数组)永久pending拒绝(AggregateError)
错误处理返回第一个错误返回第一个完成的结果返回所有错误
适用场景并行操作,全部成功执行超时控制,竞速冗余备份,任意成功

十二、Promise.allSettled封装--等待所有结果

  • 不短路:等待所有 Promise 完成(无论成功/失败)
  • 完整结果:返回每个 Promise 的最终状态和值
  • 状态无关:永远不会 reject
// 添加 allSettled 方法
Promise.allSettled = function(promises) {
  // 空数组特殊处理
  if (promises.length === 0) {
    return Promise.resolve([]);
  }

  return new Promise((resolve) => {
    const results = new Array(promises.length);
    let completed = 0;

    // 使用 for 循环代替 forEach
    for (let i = 0; i < promises.length; i++) {
      // 确保处理的是 Promise 对象
      Promise.resolve(promises[i])
        .then(value => {
          results[i] = { status: 'fulfilled', value };
        })
        .catch(reason => {
          results[i] = { status: 'rejected', reason };
        })
        .finally(() => {
          completed++;
          // 检查是否所有 Promise 都已完成
          if (completed === promises.length) {
            resolve(results);
          }
        });
    }
  });
};

十三、Promise.withResolvers -- 分离控制权

  • 控制权分离:将 Promise 的 resolve/reject 与 Promise 本身分离
  • 外部控制:可以在 Promise 外部控制其状态
// 添加 withResolvers 方法
Promise.withResolvers = function() {
  let resolve, reject;
  
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  
  return { promise, resolve, reject };
};

总结:

  • allSettled() 解决完整结果收集问题
  • withResolvers() 解决外部控制问题

十四、then方法回调的异步执行

用setTimeout模拟异步延迟回调

image.png

image.png

image.png

image.png

源码

//声明构造函数  
function Promise(executor) {  
    //添加属性  
    //设置初始状态  
    this.PromiseState = 'pending'//初始状态  
    //设置初始值  
    this.PromiseResult = null  
     //声明属性  
    this.callback = []
    //保存实例对象的this值  
    const self = this  
    //resolve函数  
    function resolve(data) {  
        //判断  
        if (self.PromiseState !== 'pending'return  
        //1.修改对象状态(PromiseState)  
        self.PromiseState = 'fulfilled'//resolved 解决  
        //2.设置对象结果值(PromiseResult)  
        self.PromiseResult = data  
        //调用成功的回调函数  
        //如果self.callback里面有onResolve  
        // if (self.callback.onResolve) {  
        //     self.callback.onResolve(data)  
        // }  
        setTimeout(() => {  
            self.callback.forEach(item => {  
                item.onResolve(data)  
            })  
        })  
    }
    //reject函数  
    function reject(data) {  
        //判断  
        if (self.PromiseState !== 'pending'return  
        //1.修改对象状态(PromiseState)  
        self.PromiseState = 'rejected'  
        //2.设置对象结果值(PromiseResult)  
        self.PromiseResult = data  
        //调用失败的回调函数  
        //如果self.callback里面有onReject
        // if (self.callback.onReject) {  
        //     self.callback.onReject(data)  
        // }  
        setTimeout(() => {  
            self.callback.forEach(item => {  
                item.onReject(data)  
            })  
        })  
    }
    try {  
        //同步调用[执行器函数]  
        executor(resolve, reject)  
    } catch (e) {  
        //修改promise对象状态为失败  
        reject(e)  
    }  
}


//添加then方法  
Promise.prototype.then = function (onResolve, onReject) {  
    const self = this  
    //判断回调函数的参数  
    if (typeof onReject !== 'function') {  
        onReject = reason => {  
            throw reason  
        }  
    }  
    //值传递 第一个不传 就给它赋默认值  
    if (typeof onResolve !== 'function') {  
        onResolve = value => value  
    }  
    return new Promise((resolve, reject) => {  
        //封装函数  
        function callback(type) {  
            try {  
                let result = type(self.PromiseResult)  
                //判断  
                if (result instanceof Promise) {  
                    //如果是promise类型对象  
                    result.then(v => {  
                        resolve(v)  
                    }, r => {  
                        reject(r)  
                    })
                 } else {  
                    //如果是非promise类型对象  
                    //结果状态为成功  
                    resolve(result)  
                }  
            } catch (e) {  
                reject(e)  
            }  
        }  
        //调用回调函数 PromiseState  
        if ( self.PromiseState === 'fulfilled') {  
            setTimeout(() => { callback(onResolve) })  
        }  
        if ( self.PromiseState === 'rejected') {  
            setTimeout(() => { callback(onReject) })  
        }  
        // (异步)回调执行时机:在改变对象状态之后才执行的回调函数  
        if ( self.PromiseState === 'pending') {  
            //保存回调函数  
             self.callback.push({  
                onResolvefunction () {  
                    callback(onResolve)  
                },  
                onRejectfunction () {  
                    callback(onReject)  
                },  
            })  
        }  
    })  
}


//添加catch方法  
Promise.prototype.catch = function (onRejected) {  
    //说明: then()的语法糖, 相当于: then(undefined, onRejected)  
    return this.then(undefined, onRejected)  
}


//添加resolve方法  
Promise.resolve = function (value) {  
    //返回Promise对象  
    return new Promise((resolve, reject) => {  
        if (value instanceof Promise) {  
            value.then(v => {  
                resolve(v)  
            }, r => {  
                reject(r)  
            })  
        } else {  
            //状态设置为成功  
            resolve(value)  
        }  
    })  
}


//添加reject方法  
Promise.reject = function (reason) {  
    return new Promise((_, reject) => {  
        reject(reason)  
    })  
}


//添加all方法  
Promise.all = function (promises) {  
    //返回结果为promise对象  
    return new Promise((resolve, reject) => {  
        let count = 0  
        let arr = []
        
         if (promises.length === 0) {
          resolve(arr);
          return;
        }
    
        //遍历  
        for (let i = 0; i < promises.length; i++) {
            // 确保处理的是 Promise 对象
             Promise.resolve(promises[i]).then(v => {  
                //得知对象的状态是成功  
                //每个promise对象都成功  
                count++  
                //将当前promise对象成果的结果存入到数组  
                arr[i] = v  
                //判断  
                if (count === promises.length) {  
                    //修改状态  
                    resolve(arr)  
                }  
            }, r => {  
                reject(r)  
            })  
        }  
    })  
}


//添加race方法  
Promise.race = function (promises) {  
    return new Promise((resolve, reject) => {
    
     if (promises.length === 0) return; // 永久pending
     
        for (let i = 0; i < promises.length; i++) {
            // 确保处理的是 Promise 对象
            Promise.resolve(promises[i]).then(v => {  
                //修改返回对象的状态为[成功]  
                resolve(v)  
            }, r => {  
                //修改返回对象的状态为[失败]  
                reject(r)  
            })  
        }  
    })  
}


//添加any方法
Promise.any = function (promises) {
  return new Promise((resolve, reject) => {
    // 用于收集所有错误
    const errors = [];
    // 记录已完成的 Promise 数量
    let completed = 0;

    // 空数组的特殊处理
    if (promises.length === 0) {
      reject(new AggregateError([], "No Promise passed"));
      return;
    }

    // 遍历所有 Promise
    for (let i = 0; i < promises.length; i++) {
      // 确保处理的是 Promise 对象
      Promise.resolve(promises[i]).then(
        // 任何一个成功就立即 resolve
        (value) => {
          resolve(value);
        },
        // 失败时收集错误
        (reason) => {
          errors[i] = reason;
          completed++;

          // 当所有 Promise 都失败时 reject
          if (completed === promises.length) {
            reject(new AggregateError(errors, "All promises were rejected"));
          }
        }
      );
    }
  })
};

// 添加 allSettled 方法
Promise.allSettled = function(promises) {
  // 空数组特殊处理
  if (promises.length === 0) {
    return Promise.resolve([]);
  }

  return new Promise((resolve) => {
    const results = new Array(promises.length);
    let completed = 0;

    // 使用 for 循环代替 forEach
    for (let i = 0; i < promises.length; i++) {
      // 确保处理的是 Promise 对象
      Promise.resolve(promises[i])
        .then(value => {
          results[i] = { status: 'fulfilled', value };
        })
        .catch(reason => {
          results[i] = { status: 'rejected', reason };
        })
        .finally(() => {
          completed++;
          // 检查是否所有 Promise 都已完成
          if (completed === promises.length) {
            resolve(results);
          }
        });
    }
  });
};

// 添加 withResolvers 方法
Promise.withResolvers = function() {
  let resolve, reject;
  
  const promise = new Promise((res, rej) => {
    resolve = res;
    reject = rej;
  });
  
  return { promise, resolve, reject };
};