美文网首页
手写promise

手写promise

作者: w_小伍 | 来源:发表于2020-11-12 10:39 被阅读0次
    /*
    * prmoise接收一个参数,执行器参数
    * 执行器参数接收两个参数:resolve,reject
    * promise有三种状态,pending,fulfilled,rejected
    * 状态一旦改变,不可逆,只能是pending-->fulfilled和pending-->rejected
    * 有状态,有保存数据的变量
    * */
    function handle(promise, callback, value, resolve, reject) {
      try {
        let result = callback(value)
        // if (promise === result) {
        //   throw new TypeError('Chaining cycle detected') // 在当前的promise里不允许返回当前的pomise
        // }
        if (result instanceof MyPromise) {
          result.then(resolve, reject) // result是一个promise实例调用then来判断当前promise的状态,
        } else {
          resolve(result) // 如果返回的不是promise,则直接改成resolve状态
        }
      } catch (e) {
        reject(e)
      }
    }
    
    class MyPromise {
      static PENDING = 'pending'
      static FULFILLED = 'fulfilled'
      static REJECTED = 'rejected'
    
      constructor(executor) { // 接收一个参数
        this.status = MyPromise.PENDING // 保存状态
        this.value = undefined  // 保存数据
        this.callbacks = [] // 当异步执行executor时,执行then的时候promise的状态还是pending,所以这时候需要把then的两个回调函数存起来
        /*
        * 执行resolve需要做的事:
        *   --改变promise的状态为fulfilled
        *   --把值传出去
        *   --只有在pending状态下时才能改变值
        *   --异步执行then的回调
        * */
        let resolve = (value) => {
          if (this.status === MyPromise.PENDING) {
            this.status = MyPromise.FULFILLED
            this.value = value
            if (this.callbacks.length) { // 执行then的回调函数是异步执行的
              setTimeout(() => {
                this.callbacks.map(cb => cb.onFulfilled(value))
              })
            }
          }
        }
        /*
        * 执行reject需要做的事:
        *   --改变promise的状态为rejected
        *   --把值传出去
        *   --只有在pending状态下时才能改变值
        *   --异步执行then的回调
        * */
        let reject = (reason) => {
          if (this.status === MyPromise.PENDING) {
            this.status = MyPromise.REJECTED
            this.value = reason
            if (this.callbacks.length) { // 执行then的回调函数是异步执行的
              setTimeout(() => {
                this.callbacks.map(cb => cb.onRejected(reason))
              })
            }
          }
        }
        try {
          executor(resolve, reject) // 接收两个函数参数
        } catch (e) { // 如果出错直接调用reject
          reject(e)
        }
      }
    
      /*
      * then需要做的事:
      *   --接收两个函数参数
      *   --返回一个新的promise
      *   --当传入的形参不是函数时,新声明一个函数并将数据返回
      *   --then的链式调用
      *   --判断当前的promise是什么状态,fulfilled状态执行第一个回调函数onFulfilled
      *     rejected状态执行第二个回调函数
      *   --onFulfilled和onRejected可能返回一个新的promise或者一个普通值
      * then的状态是根据onFulfilled, onRejected的执行结果来决定的
      * */
      then(onFulfilled, onRejected) {
        // 先判断传入的是不是函数,不是直接返回
        if (typeof onFulfilled !== 'function') {
          onFulfilled = () => this.value
        }
        if (typeof onRejected !== 'function') {
          onRejected = () => {
            throw this.value
          } // 如果是失败的,那返回的也要是失败的
        }
        // 返回一个新的promise
        let promise = new MyPromise((resolve, reject) => {
          // 判断当前promise的状态
          /*
          * 为pending时,说明执行到then的时候promise的状态还没有改变,也就是改变promise的状态的
          * 语句在定时器里执行的,所以放在任务队列里了,所以把then里的回调函数存起来,等定时器的时间到了
          * 执行resolve或者reject的时候,把then的回调函数依次执行
          * */
          if (this.status === MyPromise.PENDING) {
            this.callbacks.push({
            // 在resolve里遍历执行的时候把this.value传过来了,所以这里的value就是reslove括号里的值
              onFulfilled: value => { // onFulfilled也就是then的第一个回调函数,可能返回一个promise,所以要分两种情况
                handle(promise, onFulfilled, value, resolve, reject)
                // try {
                //   let result = onFulfilled(value)
                //   if (result instanceof MyPromise) {
                //     result.then(resolve, reject) // result是一个promise实例调用then来判断当前promise的状态,
                //   } else {
                //     resolve(value) // 如果返回的不是promise,则直接改成resolve状态
                //   }
                // } catch (e) {
                //   reject(e)
                // }
              },
              onRejected: reason => {
                handle(promise, onRejected, reason, resolve, reject)
                // try {
                //   let result = onRejected(reason)
                //   if (result instanceof MyPromise) {
                //     result.then(resolve, reject) // result是一个promise实例调用then来判断当前promise的状态,
                //   } else {
                //     resolve(reason) // 如果返回的不是promise,则直接改成resolve状态
                //   }
                // } catch (e) {
                //   reject(e)
                // }
              }
            })
          }
          /*
          * 为fulfilled状态时,说明是先改变了promise的状态,已经知道了当前promise的状态
          * 所以直接调用then的第一个回调函数,但是then的第一个回调函数onFulfilled返回的可能是一个promise
          * 所以需要判断下,也是异步执行的
          * */
          if (this.status === MyPromise.FULFILLED) {
            setTimeout(() => {
              handle(promise, onFulfilled, this.value, resolve, reject)
              // try {
              //   let result = onFulfilled(this.value)
              //   if (result instanceof MyPromise) {
              //     result.then(resolve, reject) // result是一个promise实例调用then来判断当前promise的状态,
              //   } else {
              //     resolve(result) // 如果返回的不是promise,则直接改成resolve状态
              //   }
              // } catch (e) {
              //   reject(e)
              // }
            })
          }
          if (this.status === MyPromise.REJECTED) {
            setTimeout(() => {
              try {
                handle(promise, onRejected, this.value, resolve, reject)
                // let result = onRejected(this.value)
                // if (result instanceof MyPromise) {
                //   result.then(resolve, reject) // result是一个promise实例调用then来判断当前promise的状态,
                // } else {
                //   resolve(result) // 如果返回的不是promise,则直接改成resolve状态
                // }
              } catch (e) {
                reject(e)
              }
            })
          }
        })
        return promise
      }
    
      /*
      * catch在原型上
      * */
      catch(onRejected) {
        this.then(undefined, onRejected)
      }
    
      /*
      * 返回一个promise,传人的值可能是promise,所以要判断下
      * */
      static resolve(value) {
        return new MyPromise((resolve, reject) => {
          if (value instanceof MyPromise) {
            value.then(resolve, reject)
          } else {
            resolve(value)
          }
        })
      }
    
      /*返回一个promise,只处理错误的*/
      static reject(reason) {
        return new MyPromise((resolve, reject) => {
          reject(reason)
        })
      }
    
      /*
      * 返回一个promise,只有所有的promise成功结果才是成功,只要有一个失败就失败
      * promises:是一个数组
      * */
      static all(promises) {
        if (!Array.isArray(promises)) {
          const type = typeof promises
          return new TypeError(`TypeError: ${type} ${promises} is not iterable`)
        }
        const values = new Array(promises.length) // 创建一个和传入参数数组长度一样的数组,用来保存promise成功的value
        let resolvedCount = 0 // 保存状态为resolve的个数
        return new MyPromise((resolve, reject) => {
          // 遍历promises,获取每个promise的状态
          promises.forEach((p, index) => {
            p.then(
              value => { // 执行这里的都是成功的
                values[index] = value // 保存的顺序要和传入的数组参数的顺序一样
                resolvedCount++
                if (resolvedCount === promises.length) { // 如果有失败的那这个条件将不会成立
                  resolve(values)
                }
              },
              reason => {
                reject(reason) // 只要有一个失败return的promise的状态就是reject
              }
            )
          })
        })
      }
    
      static race(promises) {
        return new MyPromise((resolve, reject) => {
          // 遍历promises,获取每个promise的状态
          promises.forEach(p => {
            p.then(
              value => { // 执行这里的都是成功的
                resolve(value)
              },
              reason => {
                reject(reason) // 只要有一个失败return的promise的状态就是reject
              }
            )
          })
        })
      }
    }
    
    

    相关文章

      网友评论

          本文标题:手写promise

          本文链接:https://www.haomeiwen.com/subject/tkwubktx.html