手撕Promise原理~~每行代码都有注释

尽量先学会使用Promise,再来看原理

#回顾下Promise基本特征

  1. promise 有三个状态:pending,resolve(也叫fulfilled) 以及 reject;
  2. new Promise时,需要传递一个执行器函数 excutor,并且立即同步执行执行器函数;
  3. excuotr 接受两个函数类型的参数,分别是resolve和reject
  4. promise默认的状态是pending状态
  5. resolve有个value值,保存成功状态的值
  6. reject 有reason值,保存失败状态的值
  7. promise状态只能从pending 到 resolve 或者pending 到 reject,状态只能改变一次
  8. promise只能通过then方法获取结果,then 接收两个参数,分别是成功回调onResolved和失败回调onRejected回调
  9. 如果调用then时,promise已经是成功状态,则执行onResolved,参数是value
  10. 如果调用then时,promise已经是失败状态,则执行onRejected,参数是reason
  11. 如果执行器中抛出异常,那么会把异常作为参数 传递给then的失败的回调onRejected

使用Promise有两种情况

        1:先改变状态,保存值,然后再指定回调函数

        2:先指定回调函数,再改变状态

show code:

     <script>
        new Promise((resolve, reject) => {
            resolve('promise') // 1: 先改变状态(同步)
        }).then((value) => {   // 2:再指定回调函数
            console.log(value)
        }, reason => {
            console.log(reason)
        })
    </script>
<script>
        new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('promise') // 2: 后改变状态(异步)
            })
        }).then((value) => {   // 1:先指定回调函数
            console.log(value)
        }, reason => {
            console.log(reason)
        })
    </script>

 对比下两者的区别

#搭建

先搭建台子,准备唱戏,如下

  1. 准备js文件,自定义Promise
  2. 准备html文件,引入上面的Promise

笔者目录如下:

html文件:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    //引入自定义promise文件
    <script src="./../lib/Promise.js"></script>
    <script>
      // 测试代码
    </script>
</body>

</html>

Promise.js文件

;(function (window) {
  /**
   * Promise构造函数
   * @param {执行器函数} excutor(同步执行)
   */
  function Promise(excutor) {
    // 定义状态常量
    const PENDING = 'pending'
    const RESOLVE = 'resolve'
    const REJECT = 'reject'
    // 保存当前this
    const self = this

    self.data = undefined // 用来存放promise结果的属性
    self.status = PENDING //指定promise对象的默认状态
    self.callbacks = [] // 用来存放回调函数 ( 先指定回调函数,再改变状态)  数据结果:{onResolved(){},onJejectd(){}}

    // 成功的promise 执行成功的回调函数
    function resolve(value) {
      // 如果当前状态不是pending状态 就结束
      if (self.status !== PENDING) return
      // 改变状态为resolve
      self.status = RESOLVE
      // 保存数据
      self.data = value
      // 如果有回调函数,则异步执行回调函数onResolved
      if (self.callbacks.length > 0) {
        // 放到队列中,保证异步执行
        setTimeout(() => {
          self.callbacks.forEach(({ onResolved }) => {
            onResolved(value)
          })
        })
      }
    }
    function reject(reason) {
      // 如果当前状态不是pending状态 就结束
      if (self.status !== PENDING) return
      // 改变状态为reject
      self.status = REJECT
      // 保存数据
      self.data = reason
      // 如果有回调函数,则异步执行回调函数onRejected
      if (self.callbacks.length > 0) {
        // 放到队列中,保证异步执行
        setTimeout(() => {
          self.callbacks.forEach(({ onRejected }) => {
            onRejected(reason)
          })
        })
      }
    }
    try {
      // 立即同步执行构造器函数
      excutor(resolve, reject)
    } catch (err) {
      //如果捕获到执行器函数excutor抛出的异常 则改为失败状态
      reject(err)
    }

    /**
     * Promise原型对象上的then方法
     * 指定成功和失败的回调函数
     * 返回一个新的Promise对象
     * @param {成功的回调} onResolved
     * @param {失败的回调} onRejected
     */
    Promise.prototype.then = function (onResolved, onRejected) {
      // 如果当前状态是pending状态 则保存回调函数 等待执行
      this.callbacks.push({
        onResolved,
        onRejected,
      })
    }
  }

  // 向外暴露Promise构造函数
  window.Promise = Promise
})(window)

至此,我们就可以测试一下了

测试代码:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script src="./../lib/Promise.js"></script>
    <script>
        new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve('这里测试手写Promise')
            })
        }).then((value) => {
            console.log('成功回调onResolved:', value)
        }, reason => {
            console.log('失败回调onRejected:', reason)
        })
    </script>
</body>

</html>

控制台输出:

成功回调onResolved: 这里测试手写Promise

现在已经实现了其中一种情况: 先指定回调函数,再改变状态 

如果我们改成另外一种情况:先改变状态,再指定回调函数来测试一下

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script src="./../lib/Promise.js"></script>
    <script>
        new Promise((resolve, reject) => {
            resolve('这里测试手写Promise')
        }).then((value) => {
            console.log('成功回调onResolved:', value)
        }, reason => {
            console.log('失败回调onRejected:', reason)
        })
    </script>
</body>

</html>

控制台不会有任何输出,我们debug代码,会发现callbacks里面是空的,callbacks里面没有回调函数,所以就不会有任何输出

因为这里是先改状态 即先执行resolve('这里测试手写Promise')  再执行then()方法

 任重而道远 接着撸

这也是最难的一步:

#完善then方法

首先得明白then方法干了些什么~

  1. 返回一个新的Promise
  2. 指定成功和失败的回调函数
  3. 如果当前promise状态是pending状态,则缓存回调函数
  4. 如果当前promise状态是resolve状态,则调用成功的回调函数onResolved
  5. 如果当前promise状态是reject状态,则调用成功的回调函数onRejected

注意:这里第四点和第五点还要进行剖析

先说第四点--回调函数onResolved的执行结果有三种情况

  1. 如果回调函数onResolved的执行结果抛出异常,则return的promise就会失败,失败的reason就是error
  2. 如果回调函数onResolved的执行结果不是promis,则return的promise就会成功,value就是返回的值
  3. 如果回调函数onResolved的执行结果是promise,则return的promise的结果就是当前promise的结果
  4. 当前promise的结果就是下面代码的const result = onResolved(this.data)的result的结果
  5. result是promise,又分为成功状态的promise和失败状态的promise

好绕口呀~

第五点和第四点的剖析是一样的,就不再赘述了

/**
     * Promise原型对象上的then方法
     * 指定成功和失败的回调函数
     * 返回一个新的Promise对象
     * @param {成功的回调} onResolved
     * @param {失败的回调} onRejected
     */
 Promise.prototype.then = function (onResolved, onRejected) {
    const self = this
  // 返回一个新的promise对象
  return new Promise((resolve, reject) => {
    if (self.status === PENDING) {
      // 如果当前状态是pending状态 则保存回调函数 等待执行
      self.callbacks.push({
        onResolved,
        onRejected,
      })
    } else if (self.status === RESOLVE) {
      // 如果当前状态是resolve状态
      // 异步执行成功回调函数
      setTimeout(() => {
        // 1: 如果执行抛出异常,return的promise就会失败,失败的reason就是error
        try {
          const result = onResolved(self.data)
          // 3: 如果result是promise,return的promise的结果就是这个promise的结果
          if (result instanceof Promise) {
            result.then(
              // 如果调用这个方法,则说明result是成功状态的promise,则返回成功状态的promise
              (value) => resolve(value),
              // 如果调用这个方法,则说明result是失败状态的promise,则返回失败状态的promise
              (reason) => reject(reason),
            )
          } else {
            // 2: 如果result不是promise return的promise就会成功,value就是返回的值
            resolve(result)
          }
        } catch (error) {
          // 捕获到异常就直接返回失败的promise
          reject(error)
        }
      })
    } else {
      // 如果当前状态是reject状态
      // 异步执行失败回调函数
      setTimeout(() => {
        onRejected(self.data)
      })
    }
  })
}

当前状态是reject状态,和resolve状态代码基本一致,只是会调用失败的回调函数onRejected

/**
 * Promise原型对象上的then方法
 * 指定成功和失败的回调函数
 * 返回一个新的Promise对象
 * @param {成功的回调} onResolved
 * @param {失败的回调} onRejected
 */
Promise.prototype.then = function (onResolved, onRejected) {
  const self = this
  // 返回一个新的promise对象
  return new Promise((resolve, reject) => {
    if (self.status === PENDING) {
      // 如果当前状态是pending状态 则保存回调函数 等待执行
      self.callbacks.push({
        onResolved,
        onRejected,
      })
    } else if (self.status === RESOLVE) {
      // 如果当前状态是resolve状态
      // 异步执行成功回调函数
      setTimeout(() => {
        // 1: 如果执行抛出异常,return的promise就会失败,失败的reason就是error
        try {
          const result = onResolved(self.data)
          // 3: 如果result是promise,return的promise的结果就是这个promise的结果
          if (result instanceof Promise) {
            result.then(
              // 如果调用这个方法,则说明result是成功状态的promise,则返回成功状态的promise
              (value) => resolve(value),
              // 如果调用这个方法,则说明result是失败状态的promise,则返回失败状态的promise
              (reason) => reject(reason),
            )
          } else {
            // 2: 如果result不是promise return的promise就会成功,value就是返回的值
            resolve(result)
          }
        } catch (error) {
          // 捕获到异常就直接返回失败的promise
          reject(error)
        }
      })
    } else {
      // 如果当前状态是reject状态
      // 异步执行失败回调函数
      setTimeout(() => {
        // 1: 如果执行抛出异常,return的promise就会失败,失败的reason就是error
        try {
          const result = onRejected(self.data)
          // 3: 如果result是promise,return的promise的结果就是这个promise的结果
          if (result instanceof Promise) {
            result.then(
              // 如果调用这个方法,则说明result是成功状态的promise,则返回成功状态的promise
              (value) => resolve(value),
              // 如果调用这个方法,则说明result是失败状态的promise,则返回失败状态的promise
              (reason) => reject(reason),
            )
          } else {
            // 2: 如果result不是promise return的promise就会成功,value就是返回的值
            resolve(result)
          }
        } catch (error) {
          // 捕获到异常就直接返回失败的promise
          reject(error)
        }
      })
    }
  })
}

写到这儿,then方法就完成一半了

接着写另外一半

当状态是pending状态的时候,现在的操作是将回调函数存起来的,如果只是存起来,不执行结果就不会影响返回的promise结果

所以这里还要这样修改下

/**
 * Promise原型对象上的then方法
 * 指定成功和失败的回调函数
 * 返回一个新的Promise对象
 * @param {成功的回调} onResolved
 * @param {失败的回调} onRejected
 */
Promise.prototype.then = function (onResolved, onRejected) {
  // 返回一个新的promise对象
  const self = this
  return new Promise((resolve, reject) => {
    if (self.status === PENDING) {
      // 如果当前状态是pending状态 回调函数的执行结果就是当前promise的结果
      self.callbacks.push({
        onResolved() {
          try {
            const result = onResolved(self.data)
            // 3: 如果result是promise,return的promise的结果就是这个promise的结果
            if (result instanceof Promise) {
              result.then(
                // 如果调用这个方法,则说明result是成功状态的promise,则返回成功状态的promise
                (value) => resolve(value),
                // 如果调用这个方法,则说明result是失败状态的promise,则返回失败状态的promise
                (reason) => reject(reason),
              )
            } else {
              // 2: 如果result不是promise return的promise就会成功,value就是返回的值
              resolve(result)
            }
          } catch (error) {
            // 捕获到异常就直接返回失败的promise
            reject(error)
          }
        },
        onRejected() {
          try {
            const result = onRejected(self.data)
            // 3: 如果result是promise,return的promise的结果就是这个promise的结果
            if (result instanceof Promise) {
              result.then(
                // 如果调用这个方法,则说明result是成功状态的promise,则返回成功状态的promise
                (value) => resolve(value),
                // 如果调用这个方法,则说明result是失败状态的promise,则返回失败状态的promise
                (reason) => reject(reason),
              )
            } else {
              // 2: 如果result不是promise return的promise就会成功,value就是返回的值
              resolve(result)
            }
          } catch (error) {
            // 捕获到异常就直接返回失败的promise
            reject(error)
          }
        },
      })
    } else if (self.status === RESOLVE) {
      // 如果当前状态是resolve状态
      // 异步执行成功回调函数
      setTimeout(() => {
        // 1: 如果执行抛出异常,return的promise就会失败,失败的reason就是error
        try {
          const result = onResolved(self.data)
          // 3: 如果result是promise,return的promise的结果就是这个promise的结果
          if (result instanceof Promise) {
            result.then(
              // 如果调用这个方法,则说明result是成功状态的promise,则返回成功状态的promise
              (value) => resolve(value),
              // 如果调用这个方法,则说明result是失败状态的promise,则返回失败状态的promise
              (reason) => reject(reason),
            )
          } else {
            // 2: 如果result不是promise return的promise就会成功,value就是返回的值
            resolve(result)
          }
        } catch (error) {
          // 捕获到异常就直接返回失败的promise
          reject(error)
        }
      })
    } else {
      // 如果当前状态是reject状态
      // 异步执行失败回调函数
      setTimeout(() => {
        // 1: 如果执行抛出异常,return的promise就会失败,失败的reason就是error
        try {
          const result = onRejected(self.data)
          // 3: 如果result是promise,return的promise的结果就是这个promise的结果
          if (result instanceof Promise) {
            result.then(
              // 如果调用这个方法,则说明result是成功状态的promise,则返回成功状态的promise
              (value) => resolve(value),
              // 如果调用这个方法,则说明result是失败状态的promise,则返回失败状态的promise
              (reason) => reject(reason),
            )
          } else {
            // 2: 如果result不是promise return的promise就会成功,value就是返回的值
            resolve(result)
          }
        } catch (error) {
          // 捕获到异常就直接返回失败的promise
          reject(error)
        }
      })
    }
  })
}

当前代码笔记冗余,稍微封装下

提取公共函数handle 传入回调函数

/**
 * Promise原型对象上的then方法
 * 指定成功和失败的回调函数
 * 返回一个新的Promise对象
 * @param {成功的回调} onResolved
 * @param {失败的回调} onRejected
 */
Promise.prototype.then = function (onResolved, onRejected) {
  const self = this
  // 返回一个新的promise对象
  return new Promise((resolve, reject) => {
    //  处理函数
    function handle(callback) {
      try {
        const result = callback(self.data)
        // 3: 如果result是promise,return的promise的结果就是这个promise的结果
        if (result instanceof Promise) {
          result.then(
            // 如果调用这个方法,则说明result是成功状态的promise,则返回成功状态的promise
            (value) => resolve(value),
            // 如果调用这个方法,则说明result是失败状态的promise,则返回失败状态的promise
            (reason) => reject(reason),
          )
        } else {
          // 2: 如果result不是promise return的promise就会成功,value就是返回的值
          resolve(result)
        }
      } catch (error) {
        // 捕获到异常就直接返回失败的promise
        reject(error)
      }
    }
    if (self.status === PENDING) {
      // 如果当前状态是pending状态 回调函数的执行结果就是当前promise的结果
      self.callbacks.push({
        onResolved() {
          handle(onResolved)
        },
        onRejected() {
          handle(onRejected)
        },
      })
    } else if (self.status === RESOLVE) {
      // 如果当前状态是resolve状态
      // 异步执行成功回调函数
      setTimeout(() => {
        handle(onResolved)
      })
    } else {
      // 如果当前状态是reject状态
      // 异步执行失败回调函数
      setTimeout(() => {
        handle(onRejected)
      })
    }
  })
}

写到这里就完成了90%了,继续~~但是可以先测试一下

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script src="./../lib/Promise.js"></script>
    <script>
        new Promise((resolve, reject) => {
            resolve('这里测试手写Promise')
        }).then((value) => {
            console.log('成功回调onResolved:', value)
        }, reason => {
            console.log('失败回调onRejected:', reason)
        })
    </script>
</body>

</html>

控制台输出:

成功回调onResolved: 这里测试手写Promise

 #错误穿透以及代码健壮性

  1. 如果onResolved不是函数,则默认向后传递数据value
  2. 如果onRejected不是函数,则向后传递失败的reason
 // 向后传递成功的value
 onResolved = typeof onResolved ? onResolved : (value) => value

 // 指定默认的失败的回调(实现异常穿透的关键点) 向后传递失败的reasonm
 onRejected = typeof onRejected === 'function'  ? onRejected : (reason) => { throw reason }

#then方法完整代码

/**
     * Promise原型对象上的then方法
     * 指定成功和失败的回调函数
     * 返回一个新的Promise对象
     * @param {成功的回调} onResolved
     * @param {失败的回调} onRejected
     */
    Promise.prototype.then = function (onResolved, onRejected) {
      // 向后传递成功的value
      onResolved = typeof onResolved ? onResolved : (value) => value
      // 指定默认的失败的回调(实现异常穿透的关键点) 向后传递失败的reasonm
      onRejected =
        typeof onRejected === 'function'
          ? onRejected
          : (reason) => {
              throw reason
            }

      const self = this
      // 返回一个新的promise对象
      return new Promise((resolve, reject) => {
        //  处理函数 根据执行的结果,改变return的promise的状态
        function handle(callback) {
          try {
            const result = callback(self.data)
            // 3: 如果result是promise,return的promise的结果就是这个promise的结果
            if (result instanceof Promise) {
              result.then(
                // 如果调用这个方法,则说明result是成功状态的promise,则返回成功状态的promise
                (value) => resolve(value),
                // 如果调用这个方法,则说明result是失败状态的promise,则返回失败状态的promise
                (reason) => reject(reason),
              )
            } else {
              // 2: 如果result不是promise return的promise就会成功,value就是返回的值
              resolve(result)
            }
          } catch (error) {
            // 捕获到异常就直接返回失败的promise
            reject(error)
          }
        }
        if (self.status === PENDING) {
          // 如果当前状态是pending状态 回调函数的执行结果就是当前promise的结果
          self.callbacks.push({
            onResolved() {
              handle(onResolved)
            },
            onRejected() {
              handle(onRejected)
            },
          })
        } else if (self.status === RESOLVE) {
          // 如果当前状态是resolve状态
          // 异步执行成功回调函数
          setTimeout(() => {
            handle(onResolved)
          })
        } else {
          // 如果当前状态是reject状态
          // 异步执行失败回调函数
          setTimeout(() => {
            handle(onRejected)
          })
        }
      })
    }

测试:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script src="./../lib/Promise.js"></script>
    <script>
        new Promise((resolve, reject) => {
            resolve('这里测试手写Promise')
        }).then((value) => {
            console.log('成功回调onResolved:', value)
            return 123
        }, reason => {
            console.log('失败回调onRejected:', reason)
        }).then(value => {
            console.log('onResolved1:', value)
        }, reason => {
            console.log('onRejected1:', reason)
        })
    </script>
</body>

</html>

浏览器输出:

 #实现catch方法


    Promise.prototype.catch = function (onRejected) {
      return this.then(undefined, onRejected)
    }

测试catch方法

<body>
    <script src="./../lib/Promise.js"></script>
    <script>
        new Promise((resovle, reject) => {
            reject(1)
        }).then(value => {
            console.log(value)
        }, reason => {
            console.log(reason) //输出 '1'
            throw '这里测试catch'
        }).catch(err => {
            console.log(err) //输出 '这里测试catch'
        })
    </script>
</body>

 浏览器输出:

 

#实现Promise.resolve静态方法

  1. resolve方法接收一个参数value
  2. value可以是promise对象,也可以不是promise对象
  3. 如果value是promise对象,则value的值就是返回的promise的值
  4. 如果value不是promise对象,则返回成功状态的promise
 // Promise函数对象的 resolve 方法
  //返回一个新的Promise对象,Promise.resolve()中可以传入Promise
  Promise.resolve = function (value) {
    // 返回一个新的promise
    return new Promise((resolve, reject) => {
      if (value instanceof Promise) {
        // value如果是promise 则value的值就是promsie的值
        // value是成功状态就调用resolve
        // value是失败状态就调用reject
        value.then(
          (value) => resolve(value),
          (reason) => reject(reason),
        )
      } else {
        //value不是promise  ==> promise变成成功,数据是value
        resolve(value)
      }
    })
  }

测试resolve方法

<body>
    <script src="./../lib/Promise.js"></script>
    <script>
        // 传入非promise对象
        const p1 = Promise.resolve(1)
        // 传入成功状态的promise
        const p2 = Promise.resolve(Promise.resolve(2))
        // 传入失败状态的promise
        const p3 = Promise.resolve(new Promise((resolve, reject) => {
            reject(3)
        }))
        p1.then(value => {
            console.log(value) // 输出 1
        })

        p2.then(value => {
            console.log(value) // 输出 2
        })

        p3.then(value => {
            console.log(value)
        }, reason => {
            console.log(reason) // 输出 3
        })

    </script>
</body>

浏览器输出:

 

 

#实现Promise.reject静态方法

  1. reject方法接收一个参数reason
  2. 返回一个失败的promise
  // Promise函数对象的 reject 方法
  //返回一个新的Promise对象 Promise.reject中不能再传入Promise
  Promise.reject = function (reason) {
    return new Promise((_, reject) => {
      reject(reason)
    })
  }

测试reject方法

<body>
    <script src="./../lib/Promise.js"></script>
    <script>
        const p1 = Promise.reject(1)

        p1.then(value => {
        }, reason => {
            console.log(reason) // 输出 1
        })
    </script>
</body>

#实现Promise.all静态方法

  1. all方法接收一个参数,其类型是一个数组
  2. 只有当全部都返回成功时,才返回成功状态的promise,否则就返回失败的promise

  // Promise函数对象的 all 方法,接受一个promise类型的数组
  // 返回一个新的Promise对象
  Promise.all = function (promises) {
    // 保证返回的值得结果的顺序和传进来的时候一致
    // 只有全部都成功长才返回成功
    const values = new Array(promises.length)
    let successCount = 0
    return new Promise((resolve, reject) => {
      promises.forEach((p, index) => {
        // 如果p不是一个Promise对象用Promise.resolve包装下
        Promise.resolve(p).then(
          (value) => {
            successCount++
            // 用下标进行赋值,因为p是异步的
            values[index] = value
            // 只有当成功的次数等于传进来的Promises的长度时,才成功
            if (successCount === promises.length) {
              resolve(values)
            }
          },
          (reason) => {
            // 只要有一个失败,就返回失败状态的promise
            reject(reason)
          },
        )
      })
    })
  }

测试all方法

<body>
    <script src="./../lib/Promise.js"></script>
    <script>
        const p1 = Promise.resolve(1)
        const p2 = Promise.resolve(2)
        const p3 = Promise.reject(3)

        const params1 = [p1, p2]
        const params2 = [p1, p2, p3]

        const result = Promise.all(params1)
        result.then(values => {
            console.log(values) //输出 [1,2]
        }, reason => {
            console.log(reason)
        })

        const result1 = Promise.all(params2)
        result1.then(value => {
            console.log(value)
        }, reason => {
            console.log(reason) // 输出 3
        })

    </script>
</body>

浏览器输出:

 #实现Promise.race静态方法

  1. 接收一个数组
  2. 只要给定的一个promise解决或拒绝,就采用第一个promise的值作为它的值
  // Promise函数对象的 race 方法,接受一个promise类型的数组
  // 返回一个新的Promise对象
  Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
      promises.forEach((p) => {
        // 谁先返回就是返回谁~~~~~
        Promise.resolve(p).then(
          (value) => {
            resolve(value)
          },
          (reason) => {
            reject(reason)
          },
        )
      })
    })
  }

测试race方法:


<body>
    <script src="./../lib/Promise.js"></script>
    <script>

        const p1 = new Promise((resolve, reject) => {
            setTimeout(() => {
                resolve(1)
            }, 1000)
        })
        const p2 = new Promise((resolve, reject) => {
            setTimeout(() => {
                reject(2)
            }, 100)
        })

        Promise.race([p1, p2]).then(value => {
            console.log(value)
        }, reason => {
            console.log(reason) //  p2先完成 所以输出 2
        })
    </script>
</body>

浏览器输出:

 Promise原理撸完了

总结一下和普通回调函数的优缺点:

回调函数的弊端:

  1. 依赖前一次的执行结果,产生回调地狱,可读性和可维护性变差
  2. 由于异步,try...catch难以捕获到异步调用的异常
  3. 并行问题,无法知道某个异步操作是否已经完成,需要设置变量来辨别

Promise是异步编程的新的解决方案,链式调用,代码可读性强,也能轻松进行错误捕获,但Promise并不是异步编程最优解,最优解应该是它的语法糖async ....await

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

superTiger_y

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值