愿你坚持不懈,努力进步,进阶成自己理想的人

—— 2017.09, 写给3年后的自己

Javascript学习总结——Promise

Promise

Promise是异步编程的一种解决方案,是一个容器,保存着某个未来才会结束的事件,然后根据未来事件
的状态做出响应

1、Promise的状态可由pending(进行中)转为resolved(完成)状态,也可以由pending转为reject(失败)状态,而且这种状态一旦转换,就不能够再改变,所以得名承诺(Promise)
2、可以将要进行的操作封装在promise对象里,用来生成Promise实例,Promise对象一经新建,就会马上执行,如:

var p = new Promise((resolved, reject) => {
  // 一些处理代码
  if(/*异步操作成功*/) {
    resolve(value);
  } else {
    reject(error);
  }
});

其中,当要表示一个异步操作执行成功的时候,就可以调用resolve函数,当发生错误的时候,则调用reject函数,然后,resolve函数和reject函数里都可以携带一个参数,这个参数的值可以传递给promise对象的then方法,传播出去,如:

p.then(value => console.log(value), error => console.log(error));

这里,这个value就是上面那段代码第4行中的value,当Promise的状态由pending变为resolved后,then方法内的语句就能马上得到执行,而若promise的状态由pending变为reject,那么第二个参数中指定的回调函数会马上得到执行。此外,p.then()的第二个参数,和p.catch()在操作上是等价的,也就是说
p.catch相当于p.then(null, callback)

p.then(value => console.log(value))
 .catch(error => console.log(error));

此外,如果promise中的异步操作抛出错误,或者运行过程中抛出错误,状态就会变成reject,就会被catch方法捕获。
3、Promise中的resolve的参数,还可以是另外一个Promise对象,表示异步操作的结果,可以是另一个异步操作,如:

var p1 = new Promise((resolve, reject) => {
  setTimeout(() => reject("Error occurs"), 2000);
});
var p2 = new Promise((resolve, reject) => {
  setTimeout(() => resolve(p1), 1000);
});

此时,p2的状态就由p1的状态所决定,也就是说因为p2的异步操作后调用了resolve(p1),然后此时p1的状态为pending,那么p2的状态不是resolved,不会执行p2.then,而是由p1的状态决定,所以p1为pending的时候,p2也为pending,最后p1为reject,那么最终p2的状态也就是reject,所以p2.catch()会得到执行
4、Promise还可以链式调用,如:

function getJSON(url) {
  var request = new XMLHttpRequest();
  return new Promise((resolve, reject) => {
    request.onreadystatechange = () => {
      if(request.readyState != 4) return;

      if(request.status == 200) {
        resolve(request.responseText);
      } else {
        reject("error!");
      }
    }
    request.open("GET", url);
    request.send();
  });
}

getJSON("data.json").then(jsonStr => {
  return getJSON("data.json");
}).then(jsonStr => {
  console.log( JSON.parse(jsonStr) );
}).catch(error => {
  console.log(error);
})

5、Promise.all(),这个方法接收一个可Iterator的对象(如Array),如:

var p = Promise.all([p1, p2, p3]);

只有p1、p2、p3的状态都是resolved,p才是resolved,否则只要有一个是rejected,那么p就是rejected
6、var p = Promise.race([p1, p2, p3]),只要p1、p2、p3中有一个resolved,那么p就是resolved
7、如果要将现有的对象转化为Promise对象,那么可以用Promise.resolve()

  • 如果参数是一个Promise对象,那么将不做任何修改,原样返回
  • 如果参数是一个thenable对象,那么将会转化为Promise对象,并立即执行then方法,如:
var thenable = {
  then: function(resolve, reject) {
    resolve("Hello");
  }
}

var p = Promise.resolve(thenable);
p.then(value => console.log(value));
// 将输出“Hello”
  • 参数不是具有then方法的对象,或者根本不是对象。那么Promise.resolve()方法将返回一个新的Promise对象,并且状态为resolved
  • 不带有任何参数,如var p = Promise.resolve(),将直接返回一个resolved状态的promise对象,而且将立即执行then方法(在本轮“事件循环”的结束时执行),如:
setTimeout(function() {
  console.log("3");
}, 0);

Promise.resolve().then(() => {
  console.log("2");
});

console.log("1");

// 输出 1 2 3