2019第三發javascript
Promise是一個構造函數,本身身上有call、resolve、reject,原型上有then、catch等方法。 Promise 對象有如下兩個特色。html
這與事件(Event)徹底不一樣,事件的特色是,若是你錯過了它,再去監聽,是得不到結果的。java
var promise = new Promise(function(resolve, reject) {
setTimeout(function(){
console.log('完成')
resolve('隨便什麼東西')
}, 2000)
})
複製代碼
相似這樣,Promise的構造函數接受一個參數:函數。而且會傳入兩個參數resolve、reject,用來表示成功或者失敗。git
通常狀況會把promise放在一個函數中,當函數調用時候纔會執行promise的操做。es6
function runAsync(){
var p = new Promise(function(resolve, reject){
//作一些異步操做
setTimeout(function(){
console.log('執行完成');
resolve('隨便什麼數據');
}, 2000);
});
return p;
}
runAsync().then(function(data){
console.log(data);
//後面能夠用傳過來的數據作些其餘操做
//......
});
複製代碼
表面上看Promise只是簡化層層的回調寫法,實質上,Promise的精髓是狀態
github
function runAsync1(){
var p = new Promise(function(resolve, reject){
//作一些異步操做
setTimeout(function(){
console.log('異步任務1執行完成');
resolve('隨便什麼數據1');
}, 1000);
});
return p;
}
function runAsync2(){
var p = new Promise(function(resolve, reject){
//作一些異步操做
setTimeout(function(){
console.log('異步任務2執行完成');
resolve('隨便什麼數據2');
}, 2000);
});
return p;
}
function runAsync3(){
var p = new Promise(function(resolve, reject){
//作一些異步操做
setTimeout(function(){
console.log('異步任務3執行完成');
resolve('隨便什麼數據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);
});
複製代碼
runAsync1()
.then(function(data){
console.log(data);
return runAsync2();
})
.then(function(data){
console.log(data);
return '直接返回數據'; //這裏直接返回數據
})
.then(function(data){
console.log(data);
});
複製代碼
reject的做用就是把Promise的狀態置爲rejected,這樣咱們在then中就能捕捉到,而後執行「失敗」狀況的回調。promise
then方法能夠接受兩個參數,第一個對應resolve的回調,第二個對應reject的回調。dom
var promise = new Promise((resolve, reject) => {
reject('失敗')
})
promise.then((data) =>{
console.log('success:' + data)
},(reason) => {
console.log('error:' + reason);
})
複製代碼
Promise除了then還有catch方法,他和then的第二個參數同樣,用來指定reject的回調。可是他還有一個做用:當在執行resolve的回調時候,若是出現異常那麼js不會卡死,而是會進入到catch方法中。
異步
當catch上面有處理reject的函數時候,會一級一級的處理,而不是直接跳到catch中。async
function getNumber(){
var p = new Promise(function(resolve, reject){
//作一些異步操做
setTimeout(function(){
var num = Math.ceil(Math.random()*10); //生成1-10的隨機數
if(num<=5){
resolve(num);
}
else{
reject('數字太大了');
}
}, 2000);
});
return p;
}
getNumber()
.then(function(data){
console.log(data);
console.log(somedata); //此處的somedata未定義
}).then((data) =>{
console.log('success:' + data)
},(reason) => {
console.log('error:' + reason);
})
.catch(function(reason){
console.error(reason);
});
複製代碼
Promise的all方法提供了並行執行異步操做的能力,而且在全部異步操做執行完後才執行回調。
Promise
.all([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
});
複製代碼
all => 誰跑的慢,以誰爲準執行回調
race => 誰跑的快,以誰爲準執行回調
Promise
.race([runAsync1(), runAsync2(), runAsync3()])
.then(function(results){
console.log(results);
});
複製代碼
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);
});
複製代碼
finally
方法用於指定無論 Promise 對象最後狀態如何,都會執行的操做。
promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});
複製代碼
finally方法的回調函數不接受任何參數,這意味着沒有辦法知道,前面的 Promise 狀態究竟是fulfilled仍是rejected。這代表,finally方法裏面的操做,應該是與狀態無關的,不依賴於 Promise 的執行結果。
finally
本質上是then
方法的特例。
var promise=new Promise(function(resolve,reject){
try {
throw new Error('test');
}catch(e){
reject(e)
}
})
複製代碼
var promise=new Promise(function(resolve,reject){
reject(new Error('test'));
})
promise.catch(function(e){
//something to deal with the error
console.log(e)
})
複製代碼
catch方面裏面還能夠再拋錯誤,這個錯誤會被後面的catch捕獲
var promise=new Promise(function(resolve,reject){
reject(new Error('test1'))
})
promise.catch(function(e){
console.log(e);
throw new Error('test2')
}).catch(function(e){
console.log(e)
})
// Error : test1
// Error : test2
複製代碼
若是組成Promise.all的promise有本身的錯誤捕獲方法,那麼Promise.all中的catch就不能捕獲該錯誤。
var p1=new Promise(function(resolve,reject){
reject(new Error('test1'))
}).catch(function(e){
console.log("由p1自身捕獲",e);
})
var p2=new Promise(function(resolve,reject){
resolve();
})
var p=Promise.all([p1,p2]);
p.then(function(){
}).catch(function(e){
//在此處捕獲不到p1中的error
console.log(e)
})
//由p1自身捕獲 Error: test1
複製代碼
在promise實例resolve以後,錯誤沒法被捕獲。
var promise=new Promise(function(resolve,reject){
resolve();
throw new Error('test');//該錯誤沒法被捕獲
})
promise.then(function(){
//
}).then(function(e){
console.log(e)
})
複製代碼
無