Promise 的简易实现

参考文档:

本实例简易实现了 angularJS $q 的服务部分内容

(function(window) {
  // Q.defer() 返回一个 Deferred 对象
  window.Q = {
    "defer": function() {
      return new Deferred();
    }
  };

  /**
   * Deferred 对象有三个方法
   * resolve 成功 改变 promise 状态为 fulfilled
   * reject 失败 改变 promise 状态为 rejected
   * notify 进度 不改变 promise 状态
   */
  function Deferred() {
    this.promise = new Promise();
  }
  Deferred.prototype.resolve = function(value) {
    if (!this.promise.isPending()) {
      return;
    }
    this.promise.getQueue().forEach(function(queue) {
      procedure("fulfilled", queue, value);
    });
    this.promise.setStatus("fulfilled", value);
  };
  Deferred.prototype.reject = function(value) {
    if (!this.promise.isPending()) {
      return;
    }
    this.promise.getQueue().forEach(function(queue) {
      procedure("rejected", queue, value);
    });
    this.promise.setStatus("rejected", value);
  };
  Deferred.prototype.notify = function(value) {
    if (!this.promise.isPending()) {
      return;
    }
    this.promise.getQueue().forEach(function(queue) {
      procedure("pending", queue, value);
    });
  };

  /**
   * 每个promise都有三个状态:pending(默认)、fulfilled(完成)、rejected(失败)
   * 默认状态可以转变为完成态或失败态,完成态与失败态之间无法相互转换,
   * 转变的过程是不可逆的,转变一旦完成promise对象就不能被修改。
   */
  function Promise() {
    this.state = "pending";
    this.queue = [];
    this.value = null;
  }
  Promise.prototype.isPending = function() {
    return "pending" === this.state;
  };
  Promise.prototype.setStatus = function(state, value) {
    this.state = state;
    this.value = value || null;
    this.queue = [];
    // 冻结对象自身的所有属性 promise 的状态是不可逆的
    Object.freeze(this);
  };
  Promise.prototype.getQueue = function() {
    return this.queue;
  };
  Promise.prototype.then = function(resolveFn, rejectFn, notifyFn) {
    var handler = {
      "fulfilled": resolveFn,
      "rejected": rejectFn,
      "pending": notifyFn
    };
    if (!this.isPending()) {
      // 允许先改变promise状态后添加回调
      procedure(this.state, handler, this.value);
    } else {
      this.queue.push(handler);
    }
    return this;
  };

  function procedure(type, handler, value) {
    var func = handler[type];
    if (isFunction(func)) {
      func(value);
    }
  }

  function isFunction(obj) {
    return "[object Function]" === Object.prototype.toString.call(obj);
  }
})(window);
<!DOCTYPE html>
<html lang="en">

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

<body>
    <script src="./src/promise.js"></script>
    <script>
        function resolveFn() {
            var defer = window.Q.defer();
            setTimeout(function () {
                defer.resolve("hi");
            }, 2000);
            return defer.promise;
        }
        var resolve = resolveFn();
        resolve.then(function (value) {
            console.log(value + " " + new Date());
        });
        setTimeout(function () {
            resolve.then(function (value) {
                console.log(value + " " + new Date());
            });
        }, 5000);

        function rejectFn() {
            var defer = window.Q.defer();
            setTimeout(function () {
                defer.reject("hi");
            }, 2000);
            return defer.promise;
        }

        rejectFn().then(function () {}, function (value) {
            console.log(value + " " + new Date());
        });
    </script>
</body>

</html>

演示效果

猜你喜欢

转载自blog.csdn.net/qq_20282263/article/details/79186247