1

Promise定义

A promise represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its then method, which registers callbacks to receive either a promise's eventual value or the reason why the promise cannot be fulfilled.Promises/A+

Promise实现

状态机

Promise实际是一个状态机,从后面需要用到的状态开始实现Promise.

var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
function Promise() {
    //存储三种状态:PENDING, FULFILLED, REJECTED.初始状态是PENDING
    var state = PENDING;
    //存储结果或者错误,一旦FULFILLED 或者 REJECTED
    var value = null;
    //存储sucess和failure处理函数,绑定在.then和.done
    var handlers = [];
}

下一步,添加两种过渡状态fulfilling和rejecting:

var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise() {
  // store state which can be PENDING, FULFILLED or REJECTED
  var state = PENDING;

  // store value once FULFILLED or REJECTED
  var value = null;

  // store sucess & failure handlers
  var handlers = [];

  function fulfill(result) {
    state = FULFILLED;
    value = result;
  }

  function reject(error) {
    state = REJECTED;
    value = error;
  }
}

上面是两种初级过渡,下面是更高级的过渡,叫做resolve:

var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;

function Promise() {
  // store state which can be PENDING, FULFILLED or REJECTED
  var state = PENDING;

  // store value once FULFILLED or REJECTED
  var value = null;

  // store sucess & failure handlers
  var handlers = [];

  function fulfill(result) {
    state = FULFILLED;
    value = result;
  }

  function reject(error) {
    state = REJECTED;
    value = error;
  }

  function resolve(result) {
    try {
      var then = getThen(result);
      if (then) {
        doResolve(then.bind(result), resolve, reject)
        return
      }
      fulfill(result);
    } catch (e) {
      reject(e);
    }
  }
}

/**
 * Check if a value is a Promise and, if it is,
 * return the `then` method of that promise.
 *
 * @param {Promise|Any} value
 * @return {Function|Null}
 */
function getThen(value) {
  var t = typeof value;
  if (value && (t === 'object' || t === 'function')) {
    var then = value.then;
    if (typeof then === 'function') {
      return then;
    }
  }
  return null;
}

/**
 * Take a potentially misbehaving resolver function and make sure
 * onFulfilled and onRejected are only called once.
 *
 * Makes no guarantees about asynchrony.
 *
 * @param {Function} fn A resolver function that may not be trusted
 * @param {Function} onFulfilled
 * @param {Function} onRejected
 */
function doResolve(fn, onFulfilled, onRejected) {
  var done = false;
  try {
    fn(function (value) {
      if (done) return
      done = true
      onFulfilled(value)
    }, function (reason) {
      if (done) return
      done = true
      onRejected(reason)
    })
  } catch (ex) {
    if (done) return
    done = true
    onRejected(ex)
  }
}

以上代码的简单实现看参考:https://github.com/then/promise/blob/master/src/core.js

Promise状态

Promise对象有以下几种状态:

  • pending: 初始状态, 非 fulfilled 或 rejected.

  • fulfilled: 成功的操作.(如果promise.then(f),立刻调用f)

  • rejected: 失败的操作.(如果promise.then(undefined, r),立刻调用r)

如果一个promise对象处在fulfilled或rejected状态而不是pending状态,那么它也可以被称为settled状态。你可能也会听到一个术语resolved,它表示promise对象处于settled状态,或者promise对象被锁定在了调用链中。settled不是一种状态,而是一种语法上的便利。

Promise方法

Promise.resolve(value/promise/thenable)

Promise.resolve(value)方法返回一个以给定值resolve掉的Promise对象。但如果这个值是thenable的(就是说带有then方法),返回的promise会“追随”这个thenable的对象,接收它的最终状态(指resolved/rejected/pendding/settled);否则这个被返回的promise对象会以这个值被fulfilled。

//Example
var p = Promise.resolve([1,2,3]);
p.then(function(v) {
  console.log(v[0]); // 1
});
//Polyfill
Promise.resolve = function (value) {
  return new Promise(function (resolve) {
    resolve(value);
  });
};

Promise.reject(reason)

Promise.reject(reason)方法返回一个用reason拒绝的Promise.

//Example
Promise.reject(new Error("fail")).then(function(error) {
  // 未被调用
}, function(error) {
  console.log(error); // 堆栈跟踪
});
//Polyfill
Promise.reject = function (value) {
  return new Promise(function (resolve, reject) {
    reject(value);
  });
};

Promise.race(iterable)

Promise.race(iterable)方法返回一个promise,这个promise在iterable中的任意一个promise被解决或拒绝后,立刻以相同的解决值被解决或以相同的拒绝原因被拒绝。

//Example
var p1 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 500, "一"); 
});
var p2 = new Promise(function(resolve, reject) { 
    setTimeout(resolve, 100, "二"); 
});

Promise.race([p1, p2]).then(function(value) {
  console.log(value); // "二"
  // 两个都解决,但p2更快
});
//Polyfill
Promise.race = function (values) {
  // TODO: this polyfill only supports array-likes
  //       it should support all iterables
  return new Promise(function (resolve, reject) {
    values.forEach(function(value){
      Promise.resolve(value).then(resolve, reject);
    });
  });
};

Promise.all(iterable)

Promise.all(iterable) 方法返回一个promise,该promise会在iterable参数内的所有promise都被解决后被解决。

//Example
var p1 = new Promise(function(resolve, reject) { 
  setTimeout(resolve, 1000, "one"); 
}); 
var p2 = new Promise(function(resolve, reject) { 
  setTimeout(resolve, 2000, "two"); 
});
var p3 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 3000, "three");
});
var p4 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 4000, "four");
});
var p5 = new Promise(function(resolve, reject) {
  reject("reject");
});

Promise.all([p1, p2, p3, p4, p5]).then(function(value) { 
  console.log(value);
}, function(reason) {
  console.log(reason)   //"reject"
});
//Polyfill
Promise.all = function (arr) {
  // TODO: this polyfill only supports array-likes
  //       it should support all iterables
  var args = Array.prototype.slice.call(arr);

  return new Promise(function (resolve, reject) {
    if (args.length === 0) return resolve([]);
    var remaining = args.length;
    function res(i, val) {
      if (val && (typeof val === 'object' || typeof val === 'function')) {
        var then = val.then;
        if (typeof then === 'function') {
          var p = new Promise(then.bind(val));
          p.then(function (val) {
            res(i, val);
          }, reject);
          return;
        }
      }
      args[i] = val;
      if (--remaining === 0) {
        resolve(args);
      }
    }
    for (var i = 0; i < args.length; i++) {
      res(i, args[i]);
    }
  });
};

Promise.prototype.then(onFulfilled, onRejected)

Promise实例具有then方法,也就是说,then方法是定义在原型对象Promise.prototype上的。它的作用是为Promise实例添加状态改变时的回调函数。

//Example
var p1 = new Promise(function(resolve, reject) {
  resolve("Success!");
  // or
  // reject ("Error!");
});

p1.then(function(value) {
  console.log(value); // Success!
}, function(reason) {
  console.log(reason); // Error!
});

Promise.prototype.catch(onRejected)

等同于调用Promise.prototype.then(undefined, onRejected)

//Example
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!"
});
//Polyfill
Promise.prototype['catch'] = function (onRejected) {
  return this.then(null, onRejected);
};

参考资源

MDN Promise
Promise官方文档
Promise对象
then/promise


sundway
1.2k 声望63 粉丝

Less is more...