Promise的使用与原理实现过程详解【附源码】

一、什么是 Promise?

Promise 是目前 JS 异步编程的一种解决方案。

  • 从语法上讲,Promise 是一个对象,从它可以获取异步操作的消息;
  • 从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。

二、Promise 原理简析?

1、Promise 本身相当于一个状态机,拥有三种状态:

  • pending(等待态)
  • fulfiled(成功态)
  • rejected(失败态)

一个 Promise 对象初始化时的状态是 pending,调用了 resolve 后会将 Promise 的状态扭转为 fulfilled,调用 reject 后会将 Promise 的状态扭转为 rejected,这两种扭转一旦发生便不能再扭转该 Promise 到其他状态。

2、Promise 对象原型上有一个 then 方法,then 方法会返回一个新的 Promise 对象,并且将回调函数 return 的结果作为该 Promise resolve 的结果,then 方法会在一个 Promise 状态被扭转为 fulfilledrejected 时被调用。then 方法的参数为两个函数,分别为 Promise 对象的状态被扭转为 fulfilledrejected 对应的回调函数。


三、Promise 的使用?

构造一个 Promise 对象,并将要执行的异步函数传入到 Promise 的参数中执行,并且在异步执行结束后调用 resolve() 函数,就可以在 Promisethen 方法中获取到异步函数的执行结果

new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve()
  }, 1000)
}).then(
  res => {},
  err => {}
)

同时在 Promise 还为我们实现了很多方便使用的方法:

  • Promise.resolve 方法

    Promise.resolve 返回一个 fulfilled 状态的 Promise

    const a = Promise.resolve(1)
    a.then(
      res => {
        // res = 1
      },
      err => {}
    )
    
  • Promise.all 方法

    Promise.all 接收一个 Promise 对象数组作为参数,只有全部的 Promise 都已经变为 fulfilled 状态后才会继续后面的处理。Promise.all 本身返回的也是一个 Promise

    const promise1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('promise1')
      }, 100)
    })
    const promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('promise2')
      }, 100)
    })
    const promises = [promise1, promise2]
    
    Promise.all(promises).then(
      res => {
        // promises 全部变为 fulfilled 状态的处理
      },
      err => {
        // promises 中有一个变为 rejected 状态的处理
      }
    )
    
  • Promise.race 方法

    Promise.racePromise.all 类似,只不过这个函数会在 Promise 中第一个 promise 的状态扭转后就开始后面的处理(fulfilledrejected 均可)

    const promise1 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('promise1')
      }, 100)
    })
    const promise2 = new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('promise2')
      }, 1000)
    })
    const promises = [promise1, promise2]
    
    Promise.race(promises).then(
      res => {
        // 此时只有 promise1 resolve 了,promise2 仍处于 pending 状态
      },
      err => {}
    )
    

四、Promise 源码实现?

  1. 首先按照最基本的 Promise 调用方式实现一个简单的 Promise (基于 ES6 规范编写),假设我们有如下调用方式:

    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve(1)
      }, 1000)
    })
      .then(
        res => {
          console.log(res)
          return 2
        },
        err => {}
      )
      .then(
        res => {
          console.log(res)
        },
        err => {}
      )
    

    我们首先要实现一个 Promise 的类,这个类的构造函数会传入一个函数作为参数,并且向该函数传入 resolvereject 两个方法。

    初始化 Promise 的状态为 pending

    class MyPromise {
      constructor(executor) {
        this.executor = executor
        this.value = null
        this.status = 'pending'
    
        const resolve = value => {
          if (this.status === 'pending') {
            this.value = value 			// 调用 resolve 后记录 resolve 的值
            this.status = 'fulfilled'   // 调用 resolve 扭转 promise 状态
          }
        }
    
        const reject = value => {
          if (this.status === 'pending') {
            this.value = value          // 调用 reject 后记录 reject 的值
            this.status = 'rejected'    // 调用 reject 扭转 promise 状态
          }
        }
    
        this.executor(resolve, reject)
    }
    
  2. 接下来要实现 Promise 对象上的 then 方法,then 方法会传入两个函数作为参数,分别作为 Promise 对象 resolvereject 的处理函数。

    这里要注意三点:

    • then 函数需要返回一个新的 Promise 对象;
    • 执行 then 函数的时候这个 Promise 的状态可能还没有被扭转为 fulfilledrejected
    • 一个 Promise 对象可以同时多次调用 then 函数;
    class MyPromise {
      constructor(executor) {
        this.executor = executor
        this.value = null
        this.status = 'pending'
        this.onFulfilledFunctions = []	// 存放这个 promise 注册的 then 函数中传的第一个函数参数
        this.onRejectedFunctions = [] 	// 存放这个 promise 注册的 then 函数中传的第二个函数参数
        
        const resolve = value => {
          if (this.status === 'pending') {
            this.value = value
            this.status = 'fulfilled'
            this.onFulfilledFunctions.forEach(onFulfilled => {
              onFulfilled() 	// 将 onFulfilledFunctions 中的函数拿出来执行
            })
          }
        }
        
        const reject = value => {
          if (this.status === 'pending') {
            this.value = value
            this.status = 'rejected'
            this.onRejectedFunctions.forEach(onRejected => {
              onRejected()		// 将 onRejectedFunctions 中的函数拿出来执行
            })
          }
        }
        
        this.executor(resolve, reject)
      }
    
      then(onFulfilled, onRejected) {
        const self = this
        if (this.status === 'pending') {
          /**
           * 当 promise 的状态仍然处于 ‘pending’ 状态时,需要将注册 onFulfilled、onRejected 方法放到 promise 的 onFulfilledFunctions、onRejectedFunctions 中备用
           */
          return new MyPromise((resolve, reject) => {
            this.onFulfilledFunctions.push(() => {
              const thenReturn = onFulfilled(self.value)
              resolve(thenReturn)
            })
            this.onRejectedFunctions.push(() => {
              const thenReturn = onRejected(self.value)
              resolve(thenReturn)
            })
          })
        } else if (this.status === 'fulfilled') {
          return new MyPromise((resolve, reject) => {
            const thenReturn = onFulfilled(self.value)
            resolve(thenReturn)
          })
        } else {
          return new MyPromise((resolve, reject) => {
            const thenReturn = onRejected(self.value)
            resolve(thenReturn)
          })
        }
      }
    }
    

    对于以上完成的 MyPromise 进行测试,测试代码如下:

    const mp = new MyPromise((resolve, reject) => {
      setTimeout(() => {
        resolve(1)
      }, 1000)
    })
    
    mp.then(res => {
      console.log('first then', res)
      return res + 1
    }).then(res => {
      console.log('first then', res)
    })
    
    mp.then(res => {
      console.log(`second then`, res)
      return res + 1
    }).then(res => {
      console.log(`second then`, res)
    })
    
    /**
     *  输出结果如下:
     *  first then 1
     *  first then 2
     *  second then 1
     *  second then 2
     */
    
  3. Promise 相关的内容中,有一点常常被我们忽略,当 then 函数中返回的是一个 Promise 应该如何处理?

    考虑如下代码:

    // 使用正确的 Promise
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve()
      }, 1000)
    })
      .then(res => {
        console.log('外部 promise')
        return new Promise((resolve, reject) => {
          resolve(`内部 promise`)
        })
      })
      .then(res => {
        console.log(res)
      })
    
    /**
     * 输出结果如下:
     * 外部 promise
     * 内部 promise
     */
    

    通过以上的输出结果不难判断,当 then 函数返回的是一个 Promise 时,Promise 并不会直接将这个 Promise 传递到下一个 then 函数,而是会等待该 Promise resolve 后,将其 resolve 的值,传递给下一个 then 函数,找到我们实现的代码的 then 函数部分,做以下修改:

    then(onFulfilled, onRejected) {
       const self = this
       if (this.status === 'pending') {
           return new MyPromise((resolve, reject) => {
           this.onFulfilledFunctions.push(() => {
               const thenReturn = onFulfilled(self.value)
               if (thenReturn instanceof MyPromise) {
                   // 当返回值为 promise 时,等该内部的 promise 状态扭转时,同步扭转外部的 promise 状态
                   thenReturn.then(resolve, reject)
               } else {
                   resolve(thenReturn)
               }
           })
           this.onRejectedFunctions.push(() => {
               const thenReturn = onRejected(self.value)
               if (thenReturn instanceof MyPromise) {
                   // 当返回值为 promise 时,等该内部的 promise 状态扭转时,同步扭转外部的 promise 状态
                   thenReturn.then(resolve, reject)
               } else {
                   resolve(thenReturn)
               }
           })
           })
       } else if (this.status === 'fulfilled') {
           return new MyPromise((resolve, reject) => {
               const thenReturn = onFulfilled(self.value)
               if (thenReturn instanceof MyPromise) {
                   // 当返回值为 promise 时,等该内部的 promise 状态扭转时,同步扭转外部的 promise 状态
                   thenReturn.then(resolve, reject)
               } else {
                   resolve(thenReturn)
               }
           })
       } else {
           return new MyPromise((resolve, reject) => {
               const thenReturn = onRejected(self.value)
               if (thenReturn instanceof MyPromise) {
                   // 当返回值为 promise 时,等该内部的 promise 状态扭转时,同步扭转外部的 promise 状态
                   thenReturn.then(resolve, reject)
               } else {
                   resolve(thenReturn)
               }
           })
       }
    }
    
  4. 现在的 Promise 实现代码仍然缺少很多细节逻辑,后面我还继续研究,来提供一个相对完整的版本。


参考文章:https://blog.csdn.net/weixin_56134381/article/details/115868041

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Promise源码实现比较复杂,这里我给你一个简化版的Promise源码示例,以帮助你理解其基本原理: ```javascript // Promise构造函数 function Promise(executor) { var self = this; self.value = null; // Promise的值 self.status = 'pending'; // Promise的状态 self.onResolvedCallbacks = []; // 存储成功回调函数的数组 self.onRejectedCallbacks = []; // 存储失败回调函数的数组 function resolve(value) { if (self.status === 'pending') { self.status = 'resolved'; self.value = value; self.onResolvedCallbacks.forEach(function (callback) { callback(value); }); } } function reject(reason) { if (self.status === 'pending') { self.status = 'rejected'; self.value = reason; self.onRejectedCallbacks.forEach(function (callback) { callback(reason); }); } } try { executor(resolve, reject); } catch (e) { reject(e); } } // then方法 Promise.prototype.then = function (onResolved, onRejected) { var self = this; var promise2; onResolved = typeof onResolved === 'function' ? onResolved : function (value) { return value; }; onRejected = typeof onRejected === 'function' ? onRejected : function (reason) { throw reason; }; if (self.status === 'resolved') { return promise2 = new Promise(function (resolve, reject) { try { var x = onResolved(self.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); } if (self.status === 'rejected') { return promise2 = new Promise(function (resolve, reject) { try { var x = onRejected(self.value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); } if (self.status === 'pending') { return promise2 = new Promise(function (resolve, reject) { self.onResolvedCallbacks.push(function (value) { try { var x = onResolved(value); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); self.onRejectedCallbacks.push(function (reason) { try { var x = onRejected(reason); resolvePromise(promise2, x, resolve, reject); } catch (e) { reject(e); } }); }); } }; // 解析Promise的状态 function resolvePromise(promise, x, resolve, reject) { var then; var thenCalledOrThrow = false; if (promise === x) { return reject(new TypeError('Chaining cycle detected for promise!')); } if (x instanceof Promise) { if (x.status === 'pending') { x.then(function (value) { resolvePromise(promise, value, resolve, reject); }, reject); } else { x.then(resolve, reject); } return; } if ((x !== null) && ((typeof x === 'object') || (typeof x === 'function'))) { try { then = x.then; if (typeof then === 'function') { then.call(x, function rs(y) { if (thenCalledOrThrow) return; thenCalledOrThrow = true; return resolvePromise(promise, y, resolve, reject); }, function rj(r) { if (thenCalledOrThrow) return; thenCalledOrThrow = true; return reject(r); }); } else { resolve(x); } } catch (e) { if (thenCalledOrThrow) return; thenCalledOrThrow = true; return reject(e); } } else { resolve(x); } } ``` 这只是一个简化版的Promise源码实现,真正的Promise实现要考虑更多的细节和边界情况。希望这个示例能帮助你更好地理解Promise的工作原理

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值