Promise
1 基础
1.1 三种状态
pending——进行中
fulfilled——已完成
rejected——已失败
只有异步操作的结果才可以决定当前是哪一种状态,其他任何操作无法改变这个状态
1.2 一旦状态改变,就不会再变
Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
1.3 缺点
- 对带逻辑的异步操作麻烦
- 无法取消Promise,一旦新建它就会立即执行,无法中途取消
- 如果不设置回调函数,Promise内部抛出的错误,不会反应到外部
- 当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)
2 基本用法
2.1 生成实例
new Promise((resolve, reject) => {
// ?做一些异步操作,最终会调用下面两者之一:
//
// resolve(someValue); // fulfilled
// ?或
// reject( err ---> "failure reason"); // rejected
});
resolve 函数作用:在异步操作成功时,将结果作为参数传递出去
reject 函数作用:在异步操作失败时,将异步操作报出的错误作为参数传递出去
2.2 then()
promise.then ( 操作成功时的回调函数 , 操作失败时的回调函数 );
成功:function ( someValue —> Promise对象传出的值 ) { … }
失败:function ( err —> Promise对象传出的值 ) { … } ( 可选 一般用 catch 方法)
链式then
若前一个then方法返回的是新的Promise实例,则后面可以再调用一个then方法
2.3 catch()
相当于 .then( null, rejection )
指定发生错误时的回调函数
特性:
- promise对象错误具有冒泡性,总是会被后面的 catch 捕获,所以catch必须
- catch 方法返回 Promise 对象,后面可以再用 then()
2.4 all()
Promise.all( [p1, p2, p3] ) 接受一个数组作为参数
- p1, p2, p3 都为 fulfilled 时 p 才为 fulfilled,返回值:组成一个数组返回给回调函数
- p1, p2, p3 其中有一个为 rejected, p就为rejected,返回值:第一个被rejected的实例的返回值,被返回给回调函数
3 实例
4 常见Promise面试题
-
了解 Promise 吗?
用同步的写法写异步的操作,来解决回调地狱的问题 -
Promise 解决的痛点是什么?
痛点:回调地狱 -
Promise 解决的痛点还有其他方法可以解决吗?如果有,请列举。
async / await -
Promise 如何使用?
初始化Promise对象,用then方法注册回调函数,用catch方法注册异常处理函数 -
Promise 常用的方法有哪些?它们的作用是什么?
then()——注册成功时的回调函数
catch()——注册失败时的回调函数 -
Promise 在事件循环中的执行过程是怎样的?
-
Promise 的业界实现都有哪些?
Q、bluebird(号称运行最快的类库) -
能不能手写一个 Promise 的 polyfill。
例子
异步加载图片
function loadImageAsync(url) {
return new Promise(function(resolve, reject) {
var image = new Image();
image.onload = function() {
resolve(image);
};
image.onerror = function() {
reject(new Error('Could not load image at ' + url));
};
image.src = url;
});
}
上面代码中,使用Promise包装了一个图片加载的异步操作。如果加载成功,就调用resolve方法,否则就调用reject方法
Promise 对象实现 Ajax 操作
var getJSON = function(url) {
var promise = new Promise(function(resolve, reject){
var client = new XMLHttpRequest();
client.open("GET", url);
client.onreadystatechange = handler;
client.responseType = "json";
client.setRequestHeader("Accept", "application/json");
client.send();
function handler() {
if (this.readyState !== 4) {
return;
}
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText));
}
};
});
return promise;
};
getJSON("/posts.json").then(function(json) {
console.log('Contents: ' + json);
}, function(error) {
console.error('出错了', error);
});
上面代码中,getJSON是对XMLHttpRequest对象的封装,用于发出一个针对JSON数据的HTTP请求,并且返回一个Promise对象。需要注意的是,在getJSON内部,resolve函数和reject函数调用时,都带有参数。