本文总结了我对ES6 Promise的理解。

对ES6 Promise的理解

一、正题

这篇文章用来谈谈我对Promise的理解。

首先Promise是一个构造函数,使用new Promise可以创建一个Promise对象。

Promise对象是一个“容器”,里面装着【异步操作】。

Promise对象有3个状态:pending(等待异步操作完成)、fulfilled(异步操作成功完成)、rejected(异步操作失败)。

当使用 new Promise() 创建一个新的Promise对象时,里面需要带一个参数,这个参数是一个函数,而这个函数的又有2个参数:resolve和reject。这里用文字表达有点难懂,直接看程序:

var pro = new Promise(function (resolve, reject) {
  // 一些异步操作
  if (异步操作成功完成) {
    resolve(value1);  // value1是异步操作成功后返回的值(如果异步操作完成后有值返回的话)
  } else {  // 异步操作失败
    reject(value2);  // value2是异步操作失败后返回的值 (如果异步操作失败后有值返回的话)
  }
});

resolve是一个函数,当调用这个函数时,Promise对象的状态从pending变成了fulfill,也就是说异步操作成功。

reject也是一个函数,当调用这个函数时,Promise对象的状态从pending变成了reject,也就是说异步操作失败。

Promise对象通过在调用resolve和reject函数时给它们传递参数,从而把异步操作返回来的信息传递出去。

Promise对象有三个方法:.then()、.catch()、.finally()。都是为Promise对象中的异步操作添加【回调函数】。

.then方法的参数是两个函数,这个两个函数作为Promise对象中异步操作的【回调函数】。第一个参数是必填的,是当Promise对象中的异步操作成功完成后,才调用的回调函数(onfulfilled);第二个参数是可选的,是当异步操作失败后,才调用的回调函数(onRejected),而这个回调函数其实一般都写在.catch()中。

.catch()方法的参数是一个函数,作为异步操作失败后,才调用的回调函数(onRejected)。

.finally()方法的参数也是一个函数,无论异步操作成功或者失败,都会调用这个函数。

.then()、.catch()中的回调函数的参数,就是Promise对象中resolve/reject的参数。

图片1

var x = 1;
var pro = new Promise(function(resolve, reject) {
    var that = this;  // 匿名函数的this指向全局window
    console.log(1);  // 同步任务
    setTimeout(function(){  // 异步任务
      if (that.x === 1) {
                resolve(2);
            } else {
                reject(3);
            }
    }, 100);
        console.log(4);  // 同步任务
});

pro
    .then(function(value1) {
        console.log(value1);
    }).catch(function(value2) {
        console.log(value2);
    });

console.log(5);

// 输出:1 4 5 2

当使用new Promise(函数X)创建一个Promise对象时,会立刻执行函数X中的同步任务。

二、应用:把Ajax封装到Promise中:

Ajax请求数据是一个异步操作,因此可以将其放到(封装到)Promise对象中:

参考:阮一峰的ES6教程

const getJSON = function(url) {
    const promise = new Promise(function(resolve, reject) {
        const handler = function() {
            if (this.readyState !== 4) {
                return;
            } 
            if (this.readyState === 200) {
                resolve(this.response);
            } else {
                reject(new Error(this.statusText));
            }
        };

        const xhr = new XMLHttpRequest();
        xhr.open("GET", url);
        xhr.onreadystatechange = handler;  // 异步操作
        xhr.responseType = "json";
        xhr.setRequestHeader("Accept", "application/json");
        xhr.send();
    });

    return promise;
};

getJSON("/posts.json")
    .then(function(json) {
        console.log("Ajax请求返回的数据:", json);
    })
    .catch(function(error) {
        console.log("出错了", error);
    });