对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的参数。

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);
});