Promise迷你书

中文版地址

什么是Promise

  • 控制异步流程的对象
  • 只能由Pending状态转换为FulfilledRejected状态,状态不可逆
  • 可以使用then方法进行接下来的处理回调

实战Promise

  • Promise.resolve/reject 包装生成promise实例
  • Promise#then
    • then方法有两个参数,分别对应成功和失败的回调
    • return 可以进行值的传递。所传值都会由Promise.resolve进行包裹,保证传值为promise实例
  • Promise#catch
    • 相当于then的特例,只有一个失败的回调
    • ie8 兼容问题 可以使用[‘catch’]去调用,避免保留字冲突;或者使用then方法去兼容
  • Promise.all 当all中所有的promise对象都成功时调用then方法
  • Promise.race 当race中存在一个结束的promise时,调用then方法

Promise测试

  • 基于mocha对promise测试
  • 普通的代码采用thencatch的流程的话比较容易理解
  • 将测试代码集中到then中处理

Advanced

  • Promise的实现类库

  • Promise.resolve 可以将thenable对象转化为promise对象,在不同的promise类库中转换可能需要thenable对象转化的操作

  • 使用reject而不是throw,更安全

  • Deferred和Promise

    • Deferred包含Promise

    • Deferred 具备对 Promise的状态进行操作的特权方法;即可以操控状态

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      function Deferred() {
      this.promise = new Promise(function (resolve, reject) {
      this._resolve = resolve;
      this._reject = reject;
      }.bind(this));
      }
      Deferred.prototype.resolve = function (value) {
      this._resolve.call(this.promise, value);
      };
      Deferred.prototype.reject = function (reason) {
      this._reject.call(this.promise, reason);
      };
    • Promise代表了一个对象,这个对象的状态现在还不确定,但是未来一个时间点它的状态要么变为正常值(FulFilled),要么变为异常值(Rejected);而Deferred对象表示了一个处理还没有结束的这种事实,在它的处理结束的时候,可以通过Promise来取得处理结果。

    • 使用Promise.race和delay取消XHR请求

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      var requestMap = {};
      function createXHRPromise(URL) {
      var req = new XMLHttpRequest();
      var promise = new Promise(function (resolve, reject) {
      req.open('GET', URL, true);
      req.onreadystatechange = function () {
      if (req.readyState === XMLHttpRequest.DONE) {
      delete requestMap[URL];
      }
      };
      req.onload = function () {
      if (req.status === 200) {
      resolve(req.responseText);
      } else {
      reject(new Error(req.statusText));
      }
      };
      req.onerror = function () {
      reject(new Error(req.statusText));
      };
      req.onabort = function () {
      reject(new Error('abort this req'));
      };
      req.send();
      });
      requestMap[URL] = {
      promise: promise,
      request: req
      };
      return promise;
      }

      function abortPromise(promise) {
      if (typeof promise === "undefined") {
      return;
      }
      var request;
      Object.keys(requestMap).some(function (URL) {
      if (requestMap[URL].promise === promise) {
      request = requestMap[URL].request;
      return true;
      }
      });
      if (request != null && request.readyState !== XMLHttpRequest.UNSENT) {
      request.abort();
      }
      }
      export {
      createXHRPromise,
      abortPromise
      }
  • done 方法(非规范,为类库实现)

    1
    2
    3
    4
    5
    6
    7
    Promise.prototype.done = function (onFulfilled, onRejected) {
    this.then(onFulfilled, onRejected).catch(function (error) {
    setTimeout(function () {
    throw error;
    }, 0);
    });
    };
    • done 方法不会返回promise

    • done 方法的异常会直接抛到外面

  • Promise方法链

    • Promisification可以转化

    • Promise并不是总是异步编程的最佳选择

    • 某些情况可以使用promise做一层封装,可以便于操作理解等

  • 使用Promise进行顺序(sequence)处理

Promises API Reference

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Promise#then
promise.then(onFulfilled, onRejected);
// Promise#catch
promise.catch(onRejected);
// Promise.resolve
Promise.resolve(promise);
Promise.resolve(thenable);
Promise.resolve(object);
// Promise.reject
Promise.reject(object)
// Promise.all
Promise.all(promiseArray);
// Promise.race
Promise.race(promiseArray);