首先,Promise是一個對象,有then()方法的對象。
then()的入?yún)⑹且粋€函數(shù),通常在promise鏈中,入?yún)⑹且粋€返回promise的函數(shù),即入?yún)⑹且粋€函數(shù),這個函數(shù)會return 一個promise對象。
- 基本用法
var p = new Promise(function(resolve,reject){
console.log(1);
setTimeout(function(){
console.log('執(zhí)行完成');
resolve("success"); //若此處不調(diào)用,則不會進入then方法
},200)
}).then(function(data){
console.log(data); //"success"
});
- 完整用法
function getNumber(){
var p = new Promise(function(resolve,reject){
var num = Math.ceil(Math.random()*10);
if(num<5){
resolve(num);
}else{
reject('數(shù)字大于5');
}
});
return p;
}
getNumber().then(function(data){
console.log(data) //3
}, function(data){
console.log(data) //數(shù)字大于5
});
- 鏈式操作用法
function runAsync1(){
var p = new Promise(function(resolve, reject){
//做一些異步操作
setTimeout(function(){
console.log('異步任務(wù)1執(zhí)行完成');
resolve('隨便什么數(shù)據(jù)1');
}, 1000);
});
return p;
}
function runAsync2(){
var p = new Promise(function(resolve, reject){
//做一些異步操作
setTimeout(function(){
console.log('異步任務(wù)2執(zhí)行完成');
resolve('隨便什么數(shù)據(jù)2');
}, 2000);
});
return p;
}
function runAsync3(){
var p = new Promise(function(resolve, reject){
//做一些異步操作
setTimeout(function(){
console.log('異步任務(wù)3執(zhí)行完成');
resolve('隨便什么數(shù)據(jù)3');
}, 2000);
});
return p;
}
runAsync1()
.then(function(data){
console.log(data);
return runAsync2();
})
.then(function(data){
console.log(data);
return runAsync3();
})
.then(function(data){
console.log(data);
});
//執(zhí)行結(jié)果:
異步任務(wù)1執(zhí)行完成
隨便什么數(shù)據(jù)1
異步任務(wù)2執(zhí)行完成
隨便什么數(shù)據(jù)2
異步任務(wù)3執(zhí)行完成
隨便什么數(shù)據(jù)3
- catch用法
//getNumber()為上述函數(shù)
getNumber()
.then(function(data){
console.log('resolved');
console.log(data);
console.log(somedata); //此處的somedata未定義
})
.catch(function(reason){
console.log('rejected');
console.log(reason);
});
//當(dāng)num<5時會輸出:
resolved
3
rejected
ReferenceError: somedata is not defined
所以catch的效果和寫在then的第二個參數(shù)里面一樣。不過它還有另外一個作用:在promise執(zhí)行中,或者執(zhí)行resolve的回調(diào)(也就是上面then中的第一個參數(shù))時,如果拋出異常了(代碼出錯了),那么并不會報錯卡死js,而是會進到這個catch方法中。
then 的第二個參數(shù)和使用 catch 的區(qū)別:
- then的第一個函數(shù)里拋出了異常,catch能捕獲到,then的第二個函數(shù)獲取不到。
- catch 并不會報錯卡死js,而是會進入到catch方法里。
- all的用法
//使用上面定義的三個函數(shù)
Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
});
//執(zhí)行結(jié)果
異步任務(wù)1執(zhí)行完成
異步任務(wù)2執(zhí)行完成
異步任務(wù)3執(zhí)行完成
["隨便什么數(shù)據(jù)1", "隨便什么數(shù)據(jù)2", "隨便什么數(shù)據(jù)3"]
Promise的all方法提供了并行執(zhí)行異步操作的能力,并且在所有異步操作執(zhí)行完后才執(zhí)行回調(diào)。
- race
//請求某個圖片資源
function requestImg(){
var p = new Promise(function(resolve, reject){
var img = new Image();
img.onload = function(){
resolve(img);
}
img.src = 'xxxxxx';
});
return p;
}
//延時函數(shù),用于給請求計時
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);
});
- 如何破壞promise鏈:
如果有這樣一個promise鏈:
//then()里面?zhèn)鞯氖且粋€返回promise對象的函數(shù)
p1().then(p2).then(p3)
.then((data)=>{
console.log('data: ' + data);
})
.catch((error)=>{
console.log('error: ' + error);
});
function p1(){
return new Promise((resolve, reject)=>{
console.log('p1 resolved');
resolve(111);
});
}
function p2(){
return new Promise((resolve, reject)=>{
console.log('p2 rejected');
reject('222');
})
}
function p3(){
return new Promise((resolve,reject)=>{
console.log('p3 resolved');
resolve(333);
})
}
//p1 resolved
//p2 rejected
//error: 222
然后再看下面:
var p1 = new Promise((resolve,reject)=>{
console.log('p1 resolved');
resolve(111);
});
var p2 = new Promise((resolve,reject)=>{
console.log('p2 rejected');
reject(222);
});
var p3 = new Promise((resolve,reject)=>{
console.log('p3 resolved');
// resolve(333);
});
p1.then(function(){
return p2;
}).then(function(){
return p3;
}).catch((error)=>{
console.log('error: ' + error)
})
p1 resolved
p2 rejected
p3 resolved
error: 222