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