资讯专栏INFORMATION COLUMN

Promise

fevin / 2280人阅读

摘要:不是一种状态,而是一种语法上的便利。方法方法返回一个以给定值掉的对象。它的作用是为实例添加状态改变时的回调函数。

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

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/78315.html

相关文章

  • Promise的几个扩展API总结

    摘要:的几个扩展总结描述和相反,当所有的被拒绝之后,方法执行完成的决议,如果存在一个执行完成的决议,方法则执行拒绝里边的所有实例反过来就好了执行到此执行到此描述忽略被拒绝的,只需要有一个完成的,方法就执行完成操作,如果全部的都被拒绝,方法执行拒绝 Promise的几个扩展API总结 1. Promise.none 描述: 和 Promise.all 相反,当所有的promise被拒绝之后,n...

    李义 评论0 收藏0
  • 异步发展流程 —— 手写一个符合 Promise/A+ 规范的 Promise

    摘要:构造函数的实现我们在使用的时候其实是使用关键字创建了一个的实例,其实是一个类,即构造函数,下面来实现构造函数。 showImg(https://segmentfault.com/img/remote/1460000018998456); 阅读原文 概述 Promise 是 js 异步编程的一种解决方案,避免了 回调地狱 给编程带来的麻烦,在 ES6 中成为了标准,这篇文章重点不是叙...

    UnixAgain 评论0 收藏0
  • Promise 对象的理解

    摘要:使用对象的好处在于可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。对象异步操作抛出错误,状态就会变为,就会调用方法指定的回调函数处理这个错误。 Promise 含义 Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了 Promise 对象。 所谓 P...

    church 评论0 收藏0
  • Promise 中的三兄弟 .all(), .race(), .allSettled()

    摘要:对于的来说基元函数包括组合函数的类型签名返回情况完成如果传入的可迭代对象为空,会同步地返回一个已完成状态的。相反,如果是在指定的时间之后完成,刚返回结果就是一个拒绝状态的从而触发方法指定的回调函数。在行中,对每个小任务得到的结果进行汇总。 为了保证的可读性,本文采用意译而非直译。 想阅读更多优质文章请猛戳GitHub博客,一年百来篇优质文章等着你! 从ES6 开始,我们大都使用的是 P...

    vspiders 评论0 收藏0
  • 实现Promise

    摘要:使用是极好的,它是如此有用以至于我觉得应该好好研究一下,甚至是实现一个简易的版本。构造函数检查参数例如是不是函数啊初始化,创建对象执行因此构造函数里面传入的是立即被执行的。 使用Promise是极好的,它是如此有用以至于我觉得应该好好研究一下Promise,甚至是实现一个简易的版本。实现之前,我们先来看看Promise的用途: 使用Promise callback hell Promi...

    xcc3641 评论0 收藏0
  • 【笔记】你不知道的JS读书笔记——Promise

    摘要:写在前面这一章的顺序对于未接触过使用过的童鞋而言略抽象了,前边几章主要为了说明和之前的异步方式相比有什么优势和它能解决什么问题,后边才详解的设计和各种场景下如何使用。建议先了解和简单使用过后再阅读,效果更佳。 写在前面:Promise这一章的顺序对于未接触过使用过Promise的童鞋而言略抽象了,前边几章主要为了说明Promise和之前的异步方式相比有什么优势和它能解决什么问题,后边才...

    mumumu 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<