ES6 -- Promise对象

梦里梦外; 2022-06-11 07:16 379阅读 0赞

Promise是一种异步编程的解决方案,ES6提供原声的Promise,它比传统的解决方案,回调函数和事件,更加合理和强大。

Promise对象有以下两个特点:

1、对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending, resulved, rejected。只有异步操作的结果,可以决定是哪一种状态。

2、状态一旦改变,就不会再变化,并且任何时候都可以得到这个结果。

实用Promise对象,可以将异步操作用同步操作的流程表达出来,避免了层层嵌套的回调函数。

基本用法

  1. var promise = new Promise(function(resolve, reject) {
  2. // ... some code
  3. if (/* 异步操作成功 */){
  4. resolve(value);
  5. } else {
  6. reject(error);
  7. }
  8. });

注意,函数resolve, reject由JS引擎提供,不用自己部署。

resolve函数的作用是将Promise对象的状态从“未完成”变为“成功”(即从 Pending 变为 Resolved),在异步调用成功的时候使用,并将异步操作的结果作为参数传递出去;reject函数将Promise对象的状态从“未完成”变为“失败”(即从 Pending 变为 Rejected),在异步操作失败时调用,并将异步操作报出的错误作为参数传递出去。

  1. promise.then(function(value) {
  2. // success
  3. }, function(error) {
  4. // failure
  5. });

Promise实例生成以后,可以用then方法分别指定Resolved状态和Rejected状态的回调函数。

一个完整的例子:

  1. function timeout(ms) {
  2. return new Promise((resolve, reject) => { setTimeout(resolve, ms, 'done'); }); } timeout(100).then((value) => { console.log(value); });

timeout方法返回一个Promise实例。当Promise实例的状态变为Resolved,就会触发then方法绑定的回调函数。

另外,Promise对象在新建后就会立即执行。

下面是用Promise对象实现Ajax的例子:

  1. var getJSON = function(url) {
  2. var promise = new Promise(function(resolve, reject){
  3. var client = new XMLHttpRequest();
  4. client.open("GET", url);
  5. client.onreadystatechange = handler;
  6. client.responseType = "json";
  7. client.setRequestHeader("Accept", "application/json");
  8. client.send();
  9. function handler() {
  10. if (this.readyState !== 4) {
  11. return;
  12. }
  13. if (this.status === 200) {
  14. resolve(this.response);
  15. } else {
  16. reject(new Error(this.statusText));
  17. }
  18. };
  19. });
  20. return promise;
  21. };
  22. getJSON("/posts.json").then(function(json) {
  23. console.log('Contents: ' + json);
  24. }, function(error) {
  25. console.error('出错了', error);
  26. });

Promise“嵌套”

如果调用resolve函数和reject函数时带有参数,那么它们的参数会被传递给回调函数。
reject函数的参数通常是Error对象的实例,表示抛出的错误;resolve函数的参数除了正常的值以外,还可能是另一个 Promise 实例:

  1. var p1 = new Promise(function (resolve, reject) {
  2. // ...
  3. });
  4. var p2 = new Promise(function (resolve, reject) {
  5. // ...
  6. resolve(p1);
  7. })

上面代码中,p1和p2都是 Promise 的实例,
但是,重要的来了,p2的resolve方法将p1作为参数,即一个异步操作的结果是返回另一个异步操作。

这时,p1的状态就会传递给p2,也就是说,p1的状态决定了p2的状态。如果p1的状态是Pending,那么p2的回调函数就会等待p1的状态改变;如果p1的状态已经是Resolved或者Rejected,那么p2的回调函数将会立刻执行。

注意,调用resolve或reject并不会终结 Promise 的参数函数的执行。

  1. new Promise((resolve, reject) => { resolve(1); console.log(2); }).then(r => { console.log(r); }); // 2 // 1

Promise.prototype.then()

then方法的作用是为 Promise 实例添加状态改变时的回调函数。前面说过,then方法的第一个参数是Resolved状态的回调函数,第二个参数(可选)是Rejected状态的回调函数。

then方法可以链式调用。

  1. getJSON("/post/1.json").then(function(post) {
  2. return getJSON(post.commentURL);
  3. }).then(function funcA(comments) {
  4. console.log("Resolved: ", comments);
  5. }, function funcB(err){
  6. console.log("Rejected: ", err);
  7. });

上面代码中,第一个then方法指定的回调函数,返回的是另一个Promise对象。这时,第二个then方法指定的回调函数,就会等待这个新的Promise对象状态发生变化。如果变为Resolved,就调用funcA,如果状态变为Rejected,就调用funcB。

Promise.prototype.catch()

Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。

另外,then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。

Promise.resolve()

Promise.resolve()可以将现有对象转化为Promise对象。

等价于:

  1. Promise.resolve('foo')
  2. // 等价于
  3. new Promise(resolve => resolve('foo'))

Promise.resolve方法的参数分成四种情况。

1、参数是一个Promise实例

如果参数是Promise实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。

2、参数是一个thenable对象

thenable对象指的是具有then方法的对象,比如下面这个对象。

  1. let thenable = {
  2. then: function(resolve, reject) {
  3. resolve(42);
  4. }
  5. };

Promise.resolve方法会将这个对象转为Promise对象,然后就立即执行thenable对象的then方法。

3、参数不是具有then方法的对象,或根本就不是对象

如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的Promise对象,状态为Resolved。

  1. var p = Promise.resolve('Hello');
  2. p.then(function (s){ console.log(s) });
  3. // Hello

4、不带有任何参数

Promise.resolve方法允许调用时不带参数,直接返回一个Resolved状态的Promise对象。

所以,如果希望得到一个Promise对象,比较方便的方法就是直接调用Promise.resolve方法。

需要注意的是,立即resolve的Promise对象,是在本轮“事件循环”(event loop)的结束时,而不是在下一轮“事件循环”的开始时。

Promise.reject()

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。

发表评论

表情:
评论列表 (有 0 条评论,379人围观)

还没有评论,来说两句吧...

相关阅读

    相关 ES6--Promise对象

    Promise对象:代表了未来某个将要发生的操作,通常是异步操作 promise对象可以将异步操作以同步的流程表达出来,避免了层层嵌套的 回调函数(回调地狱),ES6的

    相关 ES6 -- Promise对象

    Promise是一种异步编程的解决方案,ES6提供原声的Promise,它比传统的解决方案,回调函数和事件,更加合理和强大。 Promise对象有以下两个特点: 1、对象的

    相关 es6Promise 对象

    Promise 是异步编程的一种解决方案,解决——回调函数和事件 ES6 规定,Promise对象是一个构造函数,用来生成Promise实例。 下面代码创造了一个Prom

    相关 ES6标准----Promise对象

       Promise的含义:         Promise是异步编程的一种解决方法,比传统的解决方法——回调函数和事件—更合理和强大。    它由社区最早提出和实现,

    相关 ES6--Promise对象

    概述 是异步编程的一种解决方案。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。 Promise 状态 状态的特点 Promise 异步操