原生实现promise

本文探讨了如何在不使用ES6语法的情况下,手动用ES5实现Promise类及其核心功能。尽管已实现大部分功能,但还存在两个问题:一是链式调用中,当返回一个rejected状态的Promise时,无法优雅地避免未捕获异常警告;二是无法准确模拟ES6中的宏任务和微任务执行顺序。这是一个正在进行中的项目,欢迎读者提供指正。
摘要由CSDN通过智能技术生成

es6语法提供了Promise构造函数,可以很方便的进行异步操作。

因此想用es5语法手动实现一个Promise的类,并且实现它的功能。

下面上代码:

      function myPromise(callBack) {
        "use strict";
        var that = this;
        var promiseArg; //保存每次回调的参数
        var status; //保存状态数据,用于冻结并抛出异常
        var account = 0; //记录更改状态的次数
        that._status = undefined; //保存promise实例的状态
        that.handleEventArray = []; //保存事件列表
        that.finallyEvent = undefined; //finally的回调
        that.promiseArg = undefined;
        //成功、失败回调,更改状态,传入参数
        function reslove(arg) {
          that._status = true;
          that.promiseArg = promiseArg = arg;
          account++;
        }
        function reject(arg) {
          that._status = false;
          that.promiseArg = promiseArg = arg;
          account++;
        }
        //状态只能更改一次
        Object.defineProperty(that, "_status", {
          set: function(val) {
            if (account >= 1) {
              throw new Error("status can only be changed once");
            }
            status = val;
          },
          get: function() {
            return status;
          }
        });
        //依次执行回调事件
        function excuteEvent(status) {
          if (typeof status === "boolean") {
            excuteEventArray(that.handleEventArray, status);
          }
        }
        //根据当前promise状态决定如何执行回调
        function excuteEventArray(event, status) {
          debugger;
          if (event.length) {
            var currentEvent = event.shift()[+!status];
            //如果没有捕获异常回调,则
            if (typeof currentEvent === "function") {
              try {
                that.promiseArg = promiseArg = currentEvent(promiseArg);
                status = true;
              } catch (e) {
                that.promiseArg = promiseArg = e.message;
                status = false;
              }
            }

            //如果返回的是promise实例,根据实例状态执行对应的回调
            if (promiseArg instanceof myPromise) {
              status = promiseArg._status;
              that.promiseArg = promiseArg.promiseArg;
              promiseArg = that.promiseArg;
            }
            excuteEventArray(event, status);
          } else {
            //执行finally回调
            if (that.finallyEvent) {
              that.finallyEvent();
            }
            //抛出未捕获的异常
            if (!status) {
              throw new Error("Uncaught (in myPromise)  ");
            }
          }
        }
        callBack(reslove, reject);
        //用setTimeout 0 来模仿es6中的then异步
        setTimeout(excuteEvent.bind(that, that._status), 0);
      }
      function checkArgument(arg) {
        for (var i = 0; i < arg.length; i++) {
          if (typeof arg[i] !== "function" && arg[i] != null) {
            throw new Error(arg[i] + " must be an function");
          }
        }
        return true;
      }
      //快速创建promise实例的方法
      myPromise.resolve = function(e) {
        return new myPromise(function(res, rej) {
          res(e);
        });
      };
      //暂时还存在一些问题
      myPromise.reject = function(e) {
        return new myPromise(function(res, rej) {
          rej(e);
        });
      };
      myPromise.prototype = {
        then: function(res, rej) {
          var callback = function(r) {
            return r;
          };
          var that = this;
          if (checkArgument(arguments)) {
            //如果对应的处理事件是null、undefined或者没有传入,则将参数传递到下一轮回调中
            var fullfiledEvent = res == null ? callback : res;
            var rejectedEvent = rej;
            that.handleEventArray.push([fullfiledEvent, rejectedEvent]);
            return that;
          }
        },
        catch: function(event) {
          var callback = function(r) {
            return r;
          };
          if (checkArgument(arguments)) {
            //如果对应的处理事件是null、undefined或者没有传入,则将参数传递到下一轮回调中
            this.handleEventArray.push([null, event]);
          }
          return this;
        },
        finally: function(event) {
          var callback = function(r) {
            return r;
          };
          if (checkArgument(arguments)) {
            //如果对应的处理事件是null、undefined或者没有传入,则将参数传递到下一轮回调中
            this.finallyEvent = event || event;
          }
          return this;
        }
      };

目前基本完成了常用功能,不过还存在2个bug,一个是在链式调用的时候,返回一个rejected状态的promise实例时,无法阻止它报出没有捕获异常的警告。虽然可以通过很简单的方法解决,不过感觉做法并不优雅,所以以后再想想怎么优雅的完善吧。第二个bug是无法真正的模拟es6中的异步,即宏任务、微任务之间的执行顺序问题。由于es5之前是用setTimout方法实现异步,所以也没有办法解决这个问题。

以上就是实现过程。如有错漏欢迎指正。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值