1.Promise(解決異步操作問題的)
- 什么是異步
比如:函數a,執行一個步驟,a執行完要執行b;有一個順序問題;
在程序上設置a執行完執行b,一種通過回調方式,一種通過事件觸發方式; - Promise的作用
- Promise的基本用法
2.模擬ajax的過程
{
//ES5中回調解決異步操作的問題;
//前端和服務端通信有一個ajax的過程;
let ajax =function(callback){
console.log('執行');
setTimeout(function(){
//判斷這個回調是不是存在,如果存在就執行下一步;
callback && callback.call();
},1000);
};
//使用:調用這個方法,傳一個回調函數;
ajax(function(){
console.log('timeout1');
});
//輸出結果:先輸出了 執行(這個是ajax這個函數這個步驟執行的)
一秒鐘之后執行了回調函數,輸出了 timeout1;
}
3.Promise--then方法
- 如果這個過程變的復雜,先執行a在執行b,b完了之后在執行c,以此類推,用回調的方式去處理,這個代碼寫法將非常復雜;
- 這個代碼的復雜影響了后期的維護;很難一眼看出來這個回調的順序問題,到底哪個在前哪個在后;
{
let ajax = function(){
console.log('執行2');
//ajax這個函數運行完之后,返回一個對象,Promise實例,這個實例有了一個then方法,
就執行下一步的功能;
//怎么去執行呢?這里面有兩個參數resolve,reject;
//resolve:要執行下一步操作;reject:要中斷當前的操作;
return new Promise(function(resolve,reject){
setTimeout(function(){
//一秒鐘之后執行下一步的步驟;
resolve();
},1000);
});
};
//then這個參數這個函數體就是要執行的下一步;
/*
* ajax().then(function(){
* //第一個function對應的resolve;
* console.log('Promise','timeout2');
* },function(){
* //第二個function對應的是reject;
* });
*/
ajax().then(function(){
//第一個function對應的resolve;
console.log('Promise','timeout2');
});
//輸出結果:執行2 Promise timeout2
}
4.多步回調:
{
let ajax =function(){
console.log('執行3');
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve();
},1000);
});
};
ajax().then(function(){
return new Promise(function(resolve,reject){
setTimeout(function(){
resolve();
},2000);
});
}).then(function(){
console.log('timeout3');
});
//執行3 timeout3
}
5.串行過程 a b c 在中間某一步出錯,怎么捕獲這個錯誤
- Promise提供了一個catch方法,捕獲異常錯誤;
{
let ajax = function(num){
console.log('執行4');
return new Promise(function(resolve,reject){
if(num>5){
resolve();
}else{
throw new Error('出錯了');
}
);
};
ajax(6).then(function(){
console.log('log',6);
}).catch(function(err){
console.log('catch',err);
});
//log 6
ajax(3).then(function(){
console.log('log',3);
}).catch(function(err){
console.log('catch',err);
});
//catch Error:出錯了
}
6.Promise.all 和Promise.race
eg:1.所有圖片加載完在添加到頁面
{
function loadImg(src){
return new Promise((resolve,reject)=>{
let img = document.createElement('img');
img.src = src;
img.onload=function(){
resolve(img);
};
img.onerror=function(err){
reject(err);
};
});
}
function showImgs(imgs){
imgs.forEach(function(img){
document.body.appendChild(img);
});
}
//Promise.all:把多個Proimse實例當做一個Promise實例;
//all下面一個數組,數組傳遞進來多個Promise實例;當所有promise實例狀態發生改變的時候;
新的Promise實例才會跟著發生變化;
(下面這三張圖片的狀態都完成之后,才會觸發Promise.all這個新的Promise對象,所以這個
Promise對象才會有then方法;
Promise.all方法返回的是一個Promise實例,所以才可以調用then方法;
--loadImg本身是一個Promise實例,這個promise實例是做一個圖片加載的動作,把三個圖片加載
的動作放在Primose.all這個函數里面,生成一個新的promise實例,當三張圖片都加載完之后,
才會觸發顯示圖片的邏輯;
Promise.all([
loadImg('http://i4.buimg.com/567571/dflef0720bea6832.png'),
loadImg('http://i4.buimg.com/567571/2b07ee25b08930ba.png'),
loadImg('http://i2.muimg.com/567751/5eb8190d6b2a1c9c.png')
]).then(showImgs);
}
eg:2:場景:三張圖片位于三個不同的位置,頁面需要加載一張圖片,三張圖片不知道哪張返回的比較快;
- 三張圖片有三個來源,加載出來一個就可以;(先到先得)
{
//有一個圖片加載完就添加到頁面上;
function loadImg(src){
return new Promise((resolve,reject)=>{
let img = document.createElement('img');
img.src = src;
img.onload=function(){
resolve(img);
};
img.onerror=function(err){
reject(err);
};
});
}
function showImgs(img){
let p = document.createElement('p');
p.appendChild(img);
document.body.appendChild(p);
}
//多個實例中,有一個狀態先改變,最后這個race實例也會跟著改變,其他的就不在響應了;
Promise.race([
loadImg('http://i4.buimg.com/567571/dflef0720bea6832.png'),
loadImg('http://i4.buimg.com/567571/2b07ee25b08930ba.png'),
loadImg('http://i2.muimg.com/567751/5eb8190d6b2a1c9c.png')
]).then(showImgs);
//只顯示了一個;
}