Promise对象
目录
一.含义
1. Promise是什么
- promise是异步编程的一种解决方案,比传统的异步解决方案【回调函数】和【事件】更合理,更强大,已被纳入ES6规范
2. 实例讨论
问题:发送多个异步请求 并且每个请求之间需要相互依赖
-
在传统方法中,使用回调函数,通过嵌套方式来解决这个问题
- 问题:
- 代码逻辑书写顺序与执行顺序不一致,不利于阅读与维护。
- 异步操作的顺序变更时,需要大规模的代码重构。
- 回调函数基本都是匿名函数,bug 追踪困难。
- 回调函数是被第三方库代码(如上例中的 ajax )而非自己的业务代码所调用的,造成了 IoC 控制反转
$.get(url, data1 => { console.log(data1) $.get(data1.url, data2 => { console.log(data1) }) })
-
Promise处理多个互相关联的异步请求
const request = url => { return new Promise((resolve, reject) => { $.get(url, data => { resolve(data) }); }) }; // 请求data1 request(url).then(data1 => { return request(data1.url); }).then(data2 => { return request(data2.url); }).then(data3 => { console.log(data3); }).catch(err => throw new Error(err));
二.Promise特性案例解析
1. Promise的立即执行性
-
promise对象表示未来将要发生的事件,但是在创建Promise对象时,作为参数的方法是会立即执行的,只是其中执行的代码可以是异步代码
-
所以如下案例,create promise会先于after create promise执行
var p = new Promise(function(resolve,reject){ console.log('cerete promise'); resolve('success'); }) console.log('after create promise'); p.then(function(value){ console.log(value); }) // create promise // after create promise // success
2. promise的三种状态
var p1 = new Promise(function(resolve,reject){
resolve(1);
});
var p2 = new Promise(function(resolve,reject){
setTimeout(function(){
resolve(2);
}, 500);
});
var p3 = new Promise(function(resolve,reject){
setTimeout(function(){
reject(3);
}, 500);
});
console.log(p1);
console.log(p2);
console.log(p3);
setTimeout(function(){
console.log(p2);
}, 1000);
setTimeout(function(){
console.log(p3);
}, 1000);
p1.then(function(value){
console.log(value);
});
p2.then(function(value){
console.log(value);
});
p3.catch(function(err){
console.log(err);
});
- 返回值
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
1
2
3
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 2}
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: 3}
- promise有三种状态,pending,resolved,rejected。
- 当promise刚创建时,处于pending状态。
- 当promise中的参数函数执行resolve之后,promise由pending状态变为resolved状态
- 当promise中的参数函数执行reject之后,那么promise中的pending状态变为rejected状态
3. Promise的状态不可逆性
var p1 = new Promise(function(resolve, reject){
resolve("success1");
resolve("success2");
});
var p2 = new Promise(function(resolve, reject){
resolve("success");
reject("reject");
});
p1.then(function(value){
console.log(value);
});
p2.then(function(value){
console.log(value);
});
- 返回结果
success1
success
- promise中的状态一旦变成 resolved或者rejected之后,无论后续怎么调用resolve和reject方法,都无法改变promise的状态
4. 链式调用
var p = new Promise(function(resolve, reject) {
resolve(1);
});
p.then(function(value) { //第一个then
console.log(value);
return value * 2;
}).then(function(value) { //第二个then
console.log(value);
}).then(function(value) { //第三个then
console.log(value);
return Promise.resolve('resolve');
}).then(function(value) { //第四个then
console.log(value);
return Promise.reject('reject');
}).then(function(value) { //第五个then
console.log('resolve: ' + value);
}, function(err) {
console.log('reject: ' + err);
})
- 返回结果
1
2
undefined
resolve
reject:reject
- promise的then方法,返回一个新的promise对象。因此可以通过链式条用then方法
- then方法接受两个函数作为参数,第一个是promise执行成功的时候调用的方法,第二个是promise执行失败的时候调用的方法
- 以上两个函数中,只有一个会被调用
5. Promise then,回调异步性
var p = new Promise(resolve,reject){
resolve("success");
};
p.tnen(function(value){
console.log(value);
});
console.log("which one is first~");
- 返回结果
which one is first~
success
- Promise接收函数是同步执行的,但是then方法中的函数是异步执行的,所以success是后面执行的
6. Promise中的异常
var p1 = new Promise(function(resolve, reject) {
foo.bar();
resolve(1);
});
p1.then(
function(value) {
console.log('p1 then value: ' + value);
},
function(err) {
console.log('p1 then err: ' + err);
}
).then(
function(value) {
console.log('p1 then then value: ' + value);
},
function(err) {
console.log('p1 then then err: ' + err);
}
);
var p2 = new Promise(function(resolve, reject) {
resolve(2);
});
p2.then(
function(value) {
console.log('p2 then value: ' + value);
foo.bar();
},
function(err) {
console.log('p2 then err: ' + err);
}
).then(
function(value) {
console.log('p2 then then value: ' + value);
},
function(err) {
console.log('p2 then then err: ' + err);
return 1;
}
).then(
function(value) {
console.log('p2 then then then value: ' + value);
},
function(err) {
console.log('p2 then then then err: ' + err);
}
);
- 返回值
p1 then err: ReferenceError: foo is not defined
p2 then value: 2
p1 then then value: undefined
p2 then then err: ReferenceError: foo is not defined
p2 then then then value: 1
- Promise中的异常由then的第二个参数函数进行处理,异常信息将作为promise的值
- 异常一旦得到处理,then返回的后续Promise对象将恢复正常,并被promise执行成功的回调函数进行处理
- 另外要注意的是p1,p2的多级then是交替执行的
7. Promise.resolve()
- Promise.resolve()可以接受一个值或者是一个promise对象
- 当参数值为普通时,它返回一个resolved状态的promise对象,值为传的那个参数
- 当参数值为promise对象时,它直接返回这个promise对象
8. resolve VS reject
var p1 = new Promise(function(resolve, reject){
resolve(Promise.resolve('resolve'));
});
var p2 = new Promise(function(resolve, reject){
resolve(Promise.reject('reject'));
});
var p3 = new Promise(function(resolve, reject){
reject(Promise.resolve('resolve'));
});
p1.then(
function fulfilled(value){
console.log('fulfilled: ' + value);
},
function rejected(err){
console.log('rejected: ' + err);
}
);
p2.then(
function fulfilled(value){
console.log('fulfilled: ' + value);
},
function rejected(err){
console.log('rejected: ' + err);
}
);
p3.then(
function fulfilled(value){
console.log('fulfilled: ' + value);
},
function rejected(err){
console.log('rejected: ' + err);
}
);
- 返回结果
p3 rejected: [object Promise]
p1 fulfilled: resolve
p2 rejected: reject
- Promise回调函数中的第一个参数resolve,会对Promise执行’拆箱‘动作。即当resolve的参数是一个promise对象时,resolve会拆箱获取这个promise对象的值,但是这个过程是异步的。
- Promise回调函数中的第二个参数reject不会进行拆箱操作,所以reject函数中的参数直接传递给then方法中的rejected回调
三.Promise使用总结
-
初始化Promise对象
- new Promise(fn)
- Promise.resolve(fn)
-
调用上一步返回的promise实例对象的then方法,注册回调函数
-
then回调函数可以拥有一个参数,也可以不带参数。如果then中的回调函数依赖上一层返回的结果,那么要带上参数
new Promise(fn) .then(fn(value){ //处理过程 })
-
-
最后注册 catch 异常处理函数,处理前面回调中可能抛出的异常。