博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
实现promise
阅读量:6007 次
发布时间:2019-06-20

本文共 4350 字,大约阅读时间需要 14 分钟。

// 三种状态const PENDING = "pending";const RESOLVED = "resolved";const REJECTED = "rejected";// promise 接收一个函数参数,该函数会立即执行function MyPromise(fn) {  let _this = this;  _this.currentState = PENDING;  _this.value = undefined;  // 用于保存 then 中的回调,只有当 promise  // 状态为 pending 时才会缓存,并且每个实例至多缓存一个  _this.resolvedCallbacks = [];  _this.rejectedCallbacks = [];  _this.resolve = function (value) {    if (value instanceof MyPromise) {      // 如果 value 是个 Promise,递归执行      return value.then(_this.resolve, _this.reject)    }    setTimeout(() => { // 异步执行,保证执行顺序      if (_this.currentState === PENDING) {        _this.currentState = RESOLVED;        _this.value = value;        console.log(_this.resolvedCallbacks)        _this.resolvedCallbacks.forEach(cb => cb());      }    })  };  _this.reject = function (reason) {    setTimeout(() => { // 异步执行,保证执行顺序      if (_this.currentState === PENDING) {        _this.currentState = REJECTED;        _this.value = reason;        _this.rejectedCallbacks.forEach(cb => cb());      }    })  }  // 用于解决以下问题  // new Promise(() => throw Error('error))  try {    fn(_this.resolve, _this.reject);  } catch (e) {    _this.reject(e);  }}MyPromise.prototype.then = function (onResolved, onRejected) {  var self = this;  // 规范 2.2.7,then 必须返回一个新的 promise  var promise2;  // 规范 2.2.onResolved 和 onRejected 都为可选参数  // 如果类型不是函数需要忽略,同时也实现了透传  // Promise.resolve(4).then().then((value) => console.log(value))  onResolved = typeof onResolved === 'function' ? onResolved : v => v;  onRejected = typeof onRejected === 'function' ? onRejected : v => v;  if (self.currentState === RESOLVED) {    return (promise2 = new MyPromise(function (resolve, reject) {      // 规范 2.2.4,保证 onFulfilled,onRjected 异步执行      // 所以用了 setTimeout 包裹下      setTimeout(function () {        try {          var x = onResolved(self.value);          resolutionProcedure(promise2, x, resolve, reject);        } catch (reason) {          reject(reason);        }      });    }));  }  if (self.currentState === REJECTED) {    return (promise2 = new MyPromise(function (resolve, reject) {      setTimeout(function () {        // 异步执行onRejected        try {          var x = onRejected(self.value);          resolutionProcedure(promise2, x, resolve, reject);        } catch (reason) {          reject(reason);        }      });    }));  }  if (self.currentState === PENDING) {    return (promise2 = new MyPromise(function (resolve, reject) {      self.resolvedCallbacks.push(function () {        // 考虑到可能会有报错,所以使用 try/catch 包裹        try {          var x = onResolved(self.value);          resolutionProcedure(promise2, x, resolve, reject);        } catch (r) {          reject(r);        }      });      self.rejectedCallbacks.push(function () {        try {          var x = onRejected(self.value);          resolutionProcedure(promise2, x, resolve, reject);        } catch (r) {          reject(r);        }      });    }));  }};// 规范 2.3function resolutionProcedure(promise2, x, resolve, reject) {  // 规范 2.3.1,x 不能和 promise2 相同,避免循环引用  if (promise2 === x) {    return reject(new TypeError("Error"));  }  // 规范 2.3.2  // 如果 x 为 Promise,状态为 pending 需要继续等待否则执行  if (x instanceof MyPromise) {    if (x.currentState === PENDING) {      x.then(function (value) {        // 再次调用该函数是为了确认 x resolve 的        // 参数是什么类型,如果是基本类型就再次 resolve        // 把值传给下个 then        resolutionProcedure(promise2, value, resolve, reject);      }, reject);    } else {      x.then(resolve, reject);    }    return;  }  // 规范 2.3.3.3.3  // reject 或者 resolve 其中一个执行过得话,忽略其他的  let called = false;  // 规范 2.3.3,判断 x 是否为对象或者函数  if (x !== null && (typeof x === "object" || typeof x === "function")) {    // 规范 2.3.3.2,如果不能取出 then,就 reject    try {      // 规范 2.3.3.1      let then = x.then;      // 如果 then 是函数,调用 x.then      if (typeof then === "function") {        // 规范 2.3.3.3        then.call(          x,          y => {            if (called) return;            called = true;            // 规范 2.3.3.3.1            resolutionProcedure(promise2, y, resolve, reject);          },          e => {            if (called) return;            called = true;            reject(e);          }        );      } else {        // 规范 2.3.3.4        resolve(x);      }    } catch (e) {      if (called) return;      called = true;      reject(e);    }  } else {    // 规范 2.3.4,x 为基本类型    resolve(x);  }}复制代码

转载地址:http://civmx.baihongyu.com/

你可能感兴趣的文章
php有效防止同一用户多次登录
查看>>
Advanced Installer 安装前卸载旧版本的办法
查看>>
互联网产品研发策略演化
查看>>
(一)研究方法入门
查看>>
三大关系数据库字段值超长的一个有趣对比
查看>>
QT4.8.5+qt-vs-addin-1.1.11+VS2010安装配置和QT工程的新建和加载
查看>>
min宏的学习
查看>>
Qt之HTTP上传/下载
查看>>
故障排除:无法启动、访问或连接到 Azure 虚拟机上运行的应用程序
查看>>
TPshop添加后台菜单
查看>>
最全三大框架整合(使用映射)——applicationContext.xml里面的配置
查看>>
详解派生类构造函数与析构函数
查看>>
linux下获取服务器硬件信息的脚本
查看>>
apache2.4多站点配置
查看>>
[转]微信支付 支付结果通用通知
查看>>
阿里Dubbo疯狂更新,关Spring Cloud什么事?
查看>>
Java提高合集(转载)
查看>>
Android应用程序使用两个LinearLayout编排5个Button控件
查看>>
不等双十二,先入手EasyRecovery!
查看>>
微服务、SOA 和 API对比与分析
查看>>