前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >手写一个Promise Class版本及Promise的api使用方法

手写一个Promise Class版本及Promise的api使用方法

作者头像
用户10106350
发布2022-10-28 11:40:33
4380
发布2022-10-28 11:40:33
举报
文章被收录于专栏:WflynnWeb
代码语言:javascript
复制
/* 
自定义Promise函数模块: IIFE
*/
(function (window) {
 
  const PENDING = 'pending'
  const RESOLVED = 'resolved'
  const REJECTED = 'rejected'
 
  class Promise {
    /* 
    Promise构造函数
    excutor: 执行器函数(同步执行)
    */
    constructor(excutor) {
      // 将当前promise对象保存起来
      const self = this
      self.status = PENDING // 给promise对象指定status属性, 初始值为pending
      self.data = undefined // 给promise对象指定一个用于存储结果数据的属性
      self.callbacks = [] // 每个元素的结构: { onResolved() {}, onRejected() {}}
 
      function resolve (value) {
        // 如果当前状态不是pending, 直接结束
        if (self.status!==PENDING) {
          return
        }
 
        // 将状态改为resolved
        self.status = RESOLVED
        // 保存value数据
        self.data = value
        // 如果有待执行callback函数, 立即异步执行回调函数onResolved
        if (self.callbacks.length>0) {
          setTimeout(() => { // 放入队列中执行所有成功的回调
            self.callbacks.forEach(calbacksObj => {
              calbacksObj.onResolved(value)
            }) 
          });
        }
 
      }
 
      function reject (reason) {
        // 如果当前状态不是pending, 直接结束
        if (self.status!==PENDING) {
          return
        }
 
        // 将状态改为rejected
        self.status = REJECTED
        // 保存value数据
        self.data = reason
        // 如果有待执行callback函数, 立即异步执行回调函数onRejected
        if (self.callbacks.length>0) {
          setTimeout(() => { // 放入队列中执行所有成功的回调
            self.callbacks.forEach(calbacksObj => {
              calbacksObj.onRejected(reason)
            }) 
          });
        }
      }
      
      // 立即同步执行excutor
      try {
        excutor(resolve, reject)
      } catch (error) { // 如果执行器抛出异常, promise对象变为rejected状态
        reject(error)
      }
      
    }
 
代码语言:javascript
复制
  /* 
    Promise原型对象的then()
    指定成功和失败的回调函数
    返回一个新的promise对象
    返回promise的结果由onResolved/onRejected执行结果决定
    */
    then (onResolved, onRejected) {
      const self = this
 
      // 指定回调函数的默认值(必须是函数)
      onResolved = typeof onResolved==='function' ? onResolved : value => value
      onRejected = typeof onRejected==='function' ? onRejected : reason => {throw reason}
 
 
      // 返回一个新的promise
      return new Promise((resolve, reject) => {
 
        /* 
        执行指定的回调函数
        根据执行的结果改变return的promise的状态/数据
        */
        function handle(callback) {
          /* 
          返回promise的结果由onResolved/onRejected执行结果决定
          1. 抛出异常, 返回promise的结果为失败, reason为异常
          2. 返回的是promise, 返回promise的结果就是这个结果
          3. 返回的不是promise, 返回promise为成功, value就是返回值
          */
          try {
            const result = callback(self.data)
            if (result instanceof Promise) { // 2. 返回的是promise, 返回promise的结果就是这个结果
              /* 
              result.then(
                value => resolve(vlaue),
                reason => reject(reason)
              ) */
              result.then(resolve, reject)
            } else { // 3. 返回的不是promise, 返回promise为成功, value就是返回值
              resolve(result)
            }
 
          } catch (error) { // 1. 抛出异常, 返回promise的结果为失败, reason为异常
            reject(error)
          }
        }
 
        // 当前promise的状态是resolved
        if (self.status===RESOLVED) {
          // 立即异步执行成功的回调函数
          setTimeout(() => {
            handle(onResolved)
          })
        } else if (self.status===REJECTED) { // 当前promise的状态是rejected
          // 立即异步执行失败的回调函数
          setTimeout(() => {
            handle(onRejected)
          })
        } else { // 当前promise的状态是pending
          // 将成功和失败的回调函数保存callbacks容器中缓存起来
          self.callbacks.push({
            onResolved (value) {
              handle(onResolved)
            },
            onRejected (reason) {
              handle(onRejected)
            }
          })
        }
      })
    }
代码语言:javascript
复制
  /* 
    Promise原型对象的catch()
    指定失败的回调函数
    返回一个新的promise对象
    */
    catch (onRejected) {
      return this.then(undefined, onRejected)
    }
代码语言:javascript
复制
    /* 
    Promise函数对象的resolve方法
    返回一个指定结果的成功的promise
    */
    static resolve = function (value) {
      // 返回一个成功/失败的promise
      return new Promise((resolve, reject) => {
        // value是promise
        if (value instanceof Promise) { // 使用value的结果作为promise的结果
          value.then(resolve, reject)
        } else { // value不是promise  => promise变为成功, 数据是value
          resolve(value)
        }
      })
    }
代码语言:javascript
复制
    /* 
    Promise函数对象的reject方法
    返回一个指定reason的失败的promise
    */
    static reject = function (reason) {
      // 返回一个失败的promise
      return new Promise((resolve, reject) => {
        reject(reason)
      })
    }
代码语言:javascript
复制
  /* 
    Promise函数对象的all方法
    返回一个promise, 只有当所有proimse都成功时才成功, 否则只要有一个失败的就失败
    */
    static all = function (promises) {
      // 用来保存所有成功value的数组
      const values = new Array(promises.length) 
      // 用来保存成功promise的数量
      let resolvedCount = 0
      // 返回一个新的promise
      return new Promise((resolve, reject) => {
        // 遍历promises获取每个promise的结果
        promises.forEach((p, index) => {
          Promise.resolve(p).then(
            value => {
              resolvedCount++ // 成功的数量加1
              // p成功, 将成功的vlaue保存vlaues
              // values.push(value)
              values[index] = value
 
              // 如果全部成功了, 将return的promise改变成功
              if (resolvedCount===promises.length) {
                resolve(values)
              }
 
            },
            reason => { // 只要一个失败了, return的promise就失败
              reject(reason)
            }
          )
        })
      })
    }
代码语言:javascript
复制
    /* 
    Promise函数对象的race方法
    返回一个promise, 其结果由第一个完成的promise决定
    */
    static race = function (promises) {
      // 返回一个promise
      return new Promise((resolve, reject) => {
        // 遍历promises获取每个promise的结果
        promises.forEach((p, index) => {
          Promise.resolve(p).then(
            value => {// 一旦有成功了, 将return变为成功
              resolve(value)
            },
            reason => { // 一旦有失败了, 将return变为失败
              reject(reason)
            }
          )
        })
      })
    }
代码语言:javascript
复制
  /* 
    返回一个promise对象, 它在指定的时间后才确定结果
    */
    static resolveDelay = function (value, time) {
      // 返回一个成功/失败的promise
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          // value是promise
          if (value instanceof Promise) { // 使用value的结果作为promise的结果
            value.then(resolve, reject)
          } else { // value不是promise  => promise变为成功, 数据是value
            resolve(value)
          }
        }, time)
      })
    }
代码语言:javascript
复制
  /* 
    返回一个promise对象, 它在指定的时间后才失败
    */
    static rejectDelay = function (reason, time) {
      // 返回一个失败的promise
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          reject(reason)
        }, time)
      })
    }
代码语言:javascript
复制
}
 
  // 向外暴露Promise函数
  window.Promise = Promise
})(window)

Promise构造函数

Promise构造函数: Promise (excutor) {} excutor函数: 同步执行 (resolve, reject) => {} resolve函数: 内部定义成功时我们调用的函数 value => {} reject函数: 内部定义失败时我们调用的函数 reason => {} 说明:

  • excutor会在Promise内部立即同步回调,异步操作在执行器中执行(executor 函数在Promise构造函数返回所建promise实例对象前被调用)
  • resolve 和 reject 函数被调用时,分别将promise的状态改为fulfilled(完成)或rejected(失败)。
  • executor 内部通常会执行一些异步操作,一旦异步操作执行完毕(可能成功/失败),要么调用resolve函数来将promise状态改成fulfilled,要么调用reject 函数将promise的状态改为rejected。

如果在executor函数中抛出一个错误,那么该promise 状态为rejected。executor函数的返回值被忽略。

代码语言:javascript
复制
new Promise((resolve, reject) => {
    setTimeout(() => {
        // resolve('成功的数据')
        reject('失败的数据')
    }, 1000)
}).then(
    value => {
        console.log('onResolved()1', value)
    }
).catch(
    reason => {
        console.log('onRejected()1', reason)
    }
)

Promise.prototype.then()

then() 方法返回一个 Promise。它最多需要有两个参数:Promise 的成功和失败情况的回调函数。

代码语言:javascript
复制
var p1 = new Promise((resolve, reject) => {
  resolve('成功!');
  // or
  // reject(new Error("出错了!"));
});

p1.then(value => {
  console.log(value); // 成功!
}, reason => {
  console.error(reason); // 出错了!
});

返回值:当一个 Promise 完成(fulfilled)或者失败(rejected)时,返回函数将被异步调用(由当前的线程循环来调度完成)。具体的返回值依据以下规则返回。如果 then 中的回调函数:

  • 返回了一个值,那么 then 返回的 Promise 将会成为接受状态,并且将返回的值作为接受状态的回调函数的参数值。
  • 没有返回任何值,那么 then 返回的 Promise 将会成为接受状态,并且该接受状态的回调函数的参数值为 undefined
  • 抛出一个错误,那么 then 返回的 Promise 将会成为拒绝状态,并且将抛出的错误作为拒绝状态的回调函数的参数值。
  • 返回一个已经是接受状态的 Promise,那么 then 返回的 Promise 也会成为接受状态,并且将那个 Promise 的接受状态的回调函数的参数值作为该被返回的Promise的接受状态回调函数的参数值。
  • 返回一个已经是拒绝状态的 Promise,那么 then 返回的 Promise 也会成为拒绝状态,并且将那个 Promise 的拒绝状态的回调函数的参数值作为该被返回的Promise的拒绝状态回调函数的参数值。
  • 返回一个未定状态(pending)的 Promise,那么 then 返回 Promise 的状态也是未定的,并且它的终态与那个 Promise 的终态相同;同时,它变为终态时调用的回调函数参数与那个 Promise 变为终态时的回调函数的参数是相同的。

Promise.prototype.catch()

catch() 方法返回一个Promise,并且处理拒绝的情况。它的行为与调用Promise.prototype.then(undefined, onRejected) 相同

代码语言:javascript
复制
var p1 = new Promise(function(resolve, reject) {
  resolve('Success');
});

p1.then(function(value) {
  console.log(value); // "Success!"
  throw 'oh, no!';
}).catch(function(e) {
  console.log(e); // "oh, no!"
})

==== 等价于

p1.then(function(value) {
  console.log(value); // "Success!"
  return Promise.reject('oh, no!');
}).catch(function(e) {
  console.log(e); // "oh, no!"
})

在异步函数中抛出的错误不会被catch捕获到

在resolve()后面抛出的错误会被忽略

代码语言:javascript
复制
var p2 = new Promise(function(resolve, reject) {
  setTimeout(function() {
    throw 'Uncaught Exception!';
  }, 1000);
});

p2.catch(function(e) {
  console.log(e); // 不会执行
});
代码语言:javascript
复制
var p3 = new Promise(function(resolve, reject) {
  resolve();
  throw 'Silenced Exception!';
});

p3.catch(function(e) {
   console.log(e); // 不会执行
});

Promise.resolve()

代码语言:javascript
复制
Promise.resolve("Success").then(function(value) {
  console.log(value); // "Success"
}, function(value) {
  // 不会被调用
});

// resolve一个数组
var p = Promise.resolve([1,2,3]);
p.then(function(v) {
  console.log(v[0]); // 1
});

// Resolve另一个promise
var original = Promise.resolve(33);
var cast = Promise.resolve(original);
cast.then(function(value) {
  console.log('value: ' + value);
});
console.log('original === cast ? ' + (original === cast));

/*
*  打印顺序如下,这里有一个同步异步先后执行的区别
*  original === cast ? true
*  value: 33
*/

Promise.reject()

代码语言:javascript
复制
// Promise.reject(reason)方法返回一个带有拒绝原因reason参数的Promise对象。

Promise.reject("Testing static reject").then(function(reason) {
  // 未被调用
}, function(reason) {
  console.log(reason); // "Testing static reject"
});

Promise.reject(new Error("fail")).then(function(result) {
  // 未被调用
}, function(error) {
  console.log(error); // stacktrace
});

Promise.all()

返回一个新的promise, 只有所有的promise都成功才成功, 只要有一个失败了就直接失败

代码语言:javascript
复制
var p1 = Promise.resolve(3);
var p2 = 1337;
var p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([p1, p2, p3]).then(values => {
  console.log(values); // [3, 1337, "foo"]
});
var p1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, 'one');
});
var p2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 2000, 'two');
});
var p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 3000, 'three');
});
var p4 = new Promise((resolve, reject) => {
  setTimeout(resolve, 4000, 'four');
});
var p5 = new Promise((resolve, reject) => {
  reject('reject');
});

Promise.all([p1, p2, p3, p4, p5]).then(values => {
  console.log(values);
}).catch(reason => {
  console.log(reason)
});

//From console:
//"reject"

Promise.race() Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。

代码语言:javascript
复制
var promise1 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 500, 'one');
});

var promise2 = new Promise(function(resolve, reject) {
    setTimeout(resolve, 100, 'two');
});

Promise.race([promise1, promise2]).then(function(value) {
  console.log(value);
  // Both resolve, but promise2 is faster
});
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-06-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 WflynnWeb 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Promise.prototype.then()
  • Promise.prototype.catch()
  • Promise.resolve()
  • Promise.reject()
  • Promise.all()
    • Promise.race() Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝。
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档