一、介绍
主要解决的问题:嵌套深渊的问题
二、特性:
1、基本
1.Promise对象表示未来某个将要发生的事件,但在创建(new)Promise时,作为Promise参数传入的函数是会被立即执行的,只是其中执行的代码可以是异步代码
2.Promise 三种状态Pending,resolved,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"
2、链式调用
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对象
3、Promise then() 回调异步性
5.Promise then() 回调异步性
var p = new Promise(function(resolve, reject){
resolve("success");
});
p.then(function(value){
console.log(value);
});
console.log("which one is called first ?");
后台返回:
"which one is called first ?"
"success"
4、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: referfence error
p2 then value: 2
p1 then then value: 1
p2 then then err: referfence error
p2 then then then value: 1
1.漏斗调用,程序块出错,程序跳到最近一级catch,后续代码在下一级then中执行
2.如果捕获代码有return 操作,后续的then将继续执行
5、Promise.resolve()
代码示例:
var p1 = Promise.resolve( 1 );
var p2 = Promise.resolve( p1 );
var p3 = new Promise(function(resolve, reject){
resolve(1);
});
var p4 = new Promise(function(resolve, reject){
resolve(p1);
});
console.log(p1 === p2);
console.log(p1 === p3);
console.log(p1 === p4);
console.log(p3 === p4);
p4.then(function(value){
console.log('p4=' + value);
});
p2.then(function(value){
console.log('p2=' + value);
})
p1.then(function(value){
console.log('p1=' + value);
})
控制台输出结果:
true
false
false
false
p2=1
p1=1
p4=1
知识点:
Promise.resolve(...) 可以接收一个值或者是一个Promise对象作为参数。当参数是普通值时,它返回一个resolved状态的Promise对象,对象的值就是这个参数;当参数是一个Promise对象时,它直接返回这个Promise参数
为什么p4的
then*最先调用,但在控制台上是最后输出结果的呢?因为p4的resolve中接收的参数是一个Promise对象p1,resolve会对p1”拆箱“,获取p1的状态和值,但这个过程是异步的
6、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
7、Promise的不同写法
Promise.resolve 返回一个Promise对象
new Promise((res,rej)=>{ }) 适合异步执行 如:调用网络请求 调用native插件
8、Promise对作用域的影响
注意事项:
1.在ES6的类中,经常有以下写法:a.then(b).then(c)
注意 方法b 如果是类方法, 方法体内的this指向变为 undefined
解决办法: a.b用autobind b. 使用箭头函数,改变this作用域
9、Promise.all && race
Promise的all方法提供了并行执行异步操作的能力,并且在所有异步操作执行完后才执行回调。
Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
});
主要使用场景: 并行任务的效率优化<参见客户管理-登录>部分代码,获取坐标和初始化请求并行执行。
race方法
all方法的效果实际上是「谁跑的慢,以谁为准执行回调」,那么相对的就有另一个方法「谁跑的快,以谁为准执行回调」,这就是race方法,这个词本来就是赛跑的意思。race的用法与all一样
- 解决图片加载超时问题:
demo代码如下:
//请求某个图片资源
function requestImg(){
var p = new Promise(function(resolve, reject){
var img = new Image();
img.onload = function(){
resolve(img);
}
img.src = 'xxxxxx';
});
return p;
}
//延时函数,用于给请求计时
function timeout(){
var p = new Promise(function(resolve, reject){
setTimeout(function(){
reject('图片请求超时');
}, 5000);
});
return p;
}
Promise
.race([requestImg(), timeout()])
.then(function(results){
console.log(results);
})
.catch(function(reason){
console.log(reason);
});