• 手写Promise源码及方法


    原文: 本人掘金文章

    关注公众号: 微信搜索 web全栈进阶 ; 收货更多的干货

    一、Es5语法

    function MyPromise (executor) {
        this.state = 'pending'
        // 成功的值
        this.data = undefined
        // 失败的原因
        this.reason = undefined
        this.callbacks = []
    
        // 成功回调, state 重置为 resolved
        let resolve = (value) => {
          if (this.state !== 'pending') return
          this.state = 'resolved'
          this.data = value
          // 立即执行异步回调函数
          setTimeout(_ => {
            this.callbacks.forEach(callback => {
              callback.onResolved(value)
            })
          })
        }
    
        // 失败回调, state 重置为 rejected
        let reject = (reason) => {
          if (this.state !== 'pending') return
          this.state = 'rejected'
          this.reason = reason
          setTimeout(_ => {
            this.callbacks.forEach(callback => {
              callback.onRejected(reason)
            })
          })
        }
    
        // 如果executor执行报错,直接执行reject
        try{
          executor(resolve, reject)
        } catch (err) {
          reject(err)
        }
      }
    
      // Promise原型链上的then方法,可以接收两个参数(且是回调函数),成功/失败,并且每次返回的都是一个新的Promise
      MyPromise.prototype.then = function (onResolved, onRejected) {
        let _this = this
        onResolved = typeof onResolved === 'function' ? onResolved : value => value
        onRejected = typeof onRejected === 'function' ? onRejected : reason =>  console.error(reason)
        // promise对象当前状态为pending
        // 此时并不能确定调用onResolved还是onRejected,需要等待promise的状态改变
        return new MyPromise((resolve, reject) => {
    
           /*
           * 1、返回的Promise的结果是由onResolved/onrejected决定的
           * 2、返回的是Promise对象 (根据执结果决定Promise的返回结果)
           * 3、返回的不是Promise对象 (该值就是Promise的返回结果)
           * 4、抛出异常 异常的值为返回的结果
           */
    
          // 统一处理函数
          function handle (callback) {
            try {
              const result = callback(_this.data)
              if (reject instanceof MyPromise) {
                result.then(value => {
                  resolve(value)
                }, reason => {
                  reject(reason)
                })
              } else {
                resolve(result)
              }
            } catch (e) {
              reject(e)
            }
          }
    
          if (_this.state === 'resolved') {
            setTimeout(_ => {
              handle(onResolved)
            })
          }
          if (_this.state === 'rejected') {
            setTimeout(_ => {
              handle(onRejected)
            })
          }
          if (_this.state === 'pending') {
            _this.callbacks.push({
              onResolved() {
                handle(onResolved)
              },
              onRejected() {
                handle(onResolved)
              }
            })
          }
        })
      }
    
      // 错误捕获
      MyPromise.prototype.catch = function (onRejected) {
        return this.then(null, onRejected)
      }
    
      MyPromise.resolve = function (value) {
        if (value instanceof MyPromise) return value
        return new MyPromise(resolve => resolve(value))
      }
    
      MyPromise.reject = function (reason) {
        console.log(reason)
        return new MyPromise((resolve, reject) => reject(reason))  // 返回一个reject状态Promise对象
      }
    
      /*
      * Promise.all可以将多个Promise实例包装成一个新的Promise实例。
      * 同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值
      */
      MyPromise.all = function (promises) {
        if (typeof promises !== 'object' || promises.constructor !== Array) return console.error('参数需为数组!')
        let count = 0
        let values = new Array(promises.length)
        return new MyPromise((resolve,reject) => {
          promises.forEach((promise, index) => {
            MyPromise.resolve(promise).then(value => {
              count++
              values[index] = value
              if (count === promises.length) resolve(values)
            }, error => {
              reject(error)
            })
          })
        })
      }
    
      /*
      * Promise.race 返回数组实例中最先改变状态的实例(无论成功还是失败)
      *
      */
      MyPromise.race = function (promises) {
        return new MyPromise((resolve,reject) => {
          promises.forEach(promise => {
            MyPromise.resolve(promise).then(value => {
              resolve(value)
            }, error => {
              reject(error)
            })
          })
        })
      }
    

    二、Es6 class 语法

    class _Promise {
        constructor (executor) {
          const _this = this
          this.state = 'pending'
          // 成功的值
          this.data = undefined
          // 失败的原因
          this.reason = undefined
          this.callbacks = []
    
          function resolve (value) {
            if (_this.state === 'pending') return
            _this.state = 'resolved'
            _this.data = value
            setTimeout(_ => {
              _this.callbacks.forEach(callback => {
                callback.onResolved(value)
              })
            })
          }
    
          function reject (reason) {
            if (_this.state === 'pending') return
            _this.state = 'rejected'
            _this.reason = reason
            setTimeout(_ => {
              _this.callbacks.forEach(callback => {
                callback.onRejected(reason)
              })
            })
          }
    
          executor(resolve, reject)
        }
        then(onResolved, onRejected) {
          const _this = this
          onResolved = typeof onResolved === 'function' ? onResolved : value => value
          onRejected = typeof onRejected === 'function' ? onRejected : reason => console.error(reason)
    
          return new _Promise((resolve, reject) => {
            function handle (callback) {
              try {
                const result = callback(_this.data)
                if (reject instanceof _Promise) {
                  result.then(value => {
                    resolve(value)
                  }, reason => {
                    reject(reason)
                  })
                } else {
                  resolve(result)
                }
              } catch (e) {
                reject(e)
              }
            }
            if (_this.state === 'resolved') {
              setTimeout(_ => {
                handle(onResolved)
              })
            }
            if (_this.state === 'rejected') {
              setTimeout(_ => {
                handle(onRejected)
              })
            }
            if (_this.state === 'pending') {
              _this.callbacks.push({
                onResolved() {
                  handle(onResolved)
                },
                onRejected() {
                  handle(onResolved)
                }
              })
            }
          })
        }
        catch (onRejected) {
          return this.then(null, onRejected);
        }
        static resolve(value) {
          if (value instanceof _Promise) return value;
          return new _Promise(resolve => resolve(value)) // 返回一个resolved状态的新Promise对象
        }
        static reject(reason) {
          return new _Promise((resolve, reject) => reject(reason)); // 返回一个reject状态新Promise对象
        }
    
        static all(promises) {
          let count = 0
          let values = new Array(promises.length)
          return new _Promise((resolve, reject) => {
            promises.forEach((promise, index) => {
              _Promise.resolve(promise).then(value => {
                count++
                values[index] = value
                if (count === promises.length) resolve(values)
              }, reason => reject(reason))
            })
          })
        }
    
        static race(promises) {
          return new _Promise((resolve, reject) => {
            promises.forEach(promise => {
              _Promise.resolve(promise).then(value => resolve(value))
            }, reason => reject(reason))
          })
        }
      }
    

    三、测试

     /* 测试 */
      window.onload = function () {
        f3()
        let p1 = new MyPromise((resolve,reject) => {
          resolve('p1 执行完毕')
        })
        let p2 = new MyPromise((resolve,reject) => {
          resolve('p2执行完毕')
        })
        let p3 = MyPromise.reject('失败')
    
        MyPromise.all([p1, p2]).then(res => {
          console.log(res)
        }).catch(error => {
          console.log(error)
        })
    
        MyPromise.race([p1, p2, p3]).then(res => {
          console.log(res)
        }).catch(error => {
          console.log(error)
        })
      }
    
      function f1 () {
        return new _Promise((resolve,reject) => {
          f4()
          resolve(1)
        })
      }
    
      function f2 () {
        console.log('f2f2f2f2f2f2f2f2')
      }
    
      function f4 () {
        console.log('f4f4f4f4f4f4f4f4')
      }
    
      function f3 () {
        let p = f1()
        p.then(res => {
          console.log(res)
        }).catch(err => {
          console.log(err)
        })
        f2()
      }
      // 测试结果
      // f4f4f4f4f4f4f4f4
      // f2f2f2f2f2f2f2f2
      // 失败
      // ["p1 执行完毕", "p2执行完毕"]
      // p1 执行完毕
    

    参考: https://mp.weixin.qq.com/s?__biz=MzI2NTk2NzUxNg==&mid=2247488162&idx=1&sn=b0c4bdb172cb2076430569632267382d&chksm=ea941051dde39947ec94dcf3bea91250037c8bca83369fe62a61cb013fa79e13c6df5b06c78c&mpshare=1&scene=24&srcid=0822eoIZCeJt7Hy3t2Ygt3Vl&sharer_sharetime=1598055693895&sharer_shareid=50ec90ef8a78d43d2aeefdb38f1cb3a1#rd

  • 相关阅读:
    负margin实现div的左右排版
    一起来灭掉IE6!
    javac编译多个带package文件
    iis express感觉还不错
    关于sqlite使用entity framework的布署问题
    远程服务器返回了错误 NOTFOUND
    userAgent string detection in javascript
    a crossbroswer solution for parse xml fragment
    event related object in javascript
    several way to implement inheritance in javascript
  • 原文地址:https://www.cnblogs.com/ljx20180807/p/13683779.html
Copyright © 2020-2023  润新知