本篇將結合自身使用 ES6 Promise的狀況,總結下Promise在咱們項目開發中的常見的應用場景,固然,Promise 也許不是惟一選項,可是咱們做爲一個合格的前端開發人員,咱們有必要了解它。前端
語法:Promise.all(iterable)小程序
參數:一個可迭代對象,如Array。後端
返回值:微信小程序
若是傳遞的iterable爲空,則是已經解決的Promise。promise
Promise.all([]).then(res=>{
console.log(res)//[]
})
複製代碼
異步解析的Promise(若是傳遞的Iterable不包含Promise)。 請注意,在這種狀況下,Google Chrome 58返回已解決的承諾。安全
Promise.all([1,2,3]).then(res=>{
console.log(res)//[1,2,3]
})
複製代碼
當給定可迭代對象中的全部promise已解決,或者任何promise均被拒絕時,此返回的promise將被異步解析/拒絕(堆棧爲空時)微信
let promise1 = new Promise((resolve,reject)=>{
resolve(1)
})
let promise2 = new Promise((resolve,reject)=>{
resolve(2)
})
Promise.all([promise1,promise2,3]).then(res=>{
console.log(res)//[1,2,3]
})
複製代碼
let promise1 = new Promise((resolve,reject)=>{
resolve(1)
})
let promise2 = new Promise((resolve,reject)=>{
reject(2)
})
Promise.all([promise1,promise2,3]).then(res=>{
console.log(res)
}).catch(err=>{
console.log(err)//2
})
複製代碼
描述:網絡
此方法對於彙總多個promise的結果頗有用, 在ES6中能夠將多個Promise.all異步請求並行操做:併發
1.當全部結果成功返回時按照請求順序返回成功;異步
2.當其中有一個失敗方法時,則進入失敗方法;
具體描述:一個頁面,有多個請求,咱們需求全部的請求都返回數據後再一塊兒處理渲染
思考:若是併發請求的話,每一個請求的loading狀態要單獨設置,多個的話可能多個loading 重合,頁面顯示的內容 根據請求返回數據的快慢 有所差別,具體表如今渲染的過程,爲提高用戶體驗,咱們能夠採用 全部請求返回數據後,再一塊兒渲染,此時咱們關閉請求的單獨loading設置,經過Promise.all 彙總請求結果,從開始到結束,咱們只設置一個 loading 便可。
//1.獲取輪播數據列表
function getBannerList(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('輪播數據')
},300)
})
}
//2.獲取店鋪列表
function getStoreList(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('店鋪數據')
},500)
})
}
//3.獲取分類列表
function getCategoryList(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('分類數據')
},700)
})
}
function initLoad(){
// loading.show() //加載loading
Promise.all([getBannerList(),getStoreList(),getCategoryList()]).then(res=>{
console.log(res)
// loading.hide() //關閉loading
}).catch(err=>{
console.log(err)
// loading.hide()//關閉loading
})
}
//數據初始化
initLoad()
複製代碼
描述:咱們需求單獨處理一個請求的數據渲染和錯誤處理邏輯,有多個請求,咱們就須要在多個地方寫
思考:咱們可否把多個請求合併在一塊兒,哪怕有的請求失敗了,也返回給咱們,咱們只須要在一個地方處理這些數據和錯誤的邏輯便可。
//1.獲取輪播圖數據列表
function getBannerList(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
// resolve('輪播圖數據')
reject('獲取輪播圖數據失敗啦')
},300)
})
}
//2.獲取店鋪列表
function getStoreList(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('店鋪數據')
},500)
})
}
//3.獲取分類列表
function getCategoryList(){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve('分類數據')
},700)
})
}
function initLoad(){
// loading.show()
Promise.all([
getBannerList().catch(err=>err),
getStoreList().catch(err=>err),
getCategoryList().catch(err=>err)
]).then(res=>{
console.log(res) // ["獲取輪播圖數據失敗啦", "店鋪數據", "分類數據"]
if(res[0] == '輪播圖數據'){
//渲染
}else{
//獲取 輪播圖數據 失敗的邏輯
}
if(res[1] == '店鋪數據'){
//渲染
}else{
//獲取 店鋪列表數據 失敗的邏輯
}
if(res[2] == '分類數據'){
//渲染
}else{
//獲取 分類列表數據 失敗的邏輯
}
// loading.hide()
})
}
initLoad()
複製代碼
有時候頁面掛掉了,可能由於接口異常致使,或許只是一個可有可無的接口掛掉了。那麼一個接口掛掉了爲何會致使整個頁面無數據呢?Promise.all告訴咱們,若是參數中 promise 有一個失敗(rejected),此實例回調失敗(reject),就再也不執行then方法回調,以上用例 正好能夠解決此種問題
描述:在一個微信小程序項目中,作一個表單的輸入內容安全驗證,調用的是雲函數寫的方法,表單有多7個字段須要驗證,都是調用的一個 內容安全校驗接口,所有驗證經過則 能夠 進行正常的提交
function verify1(content){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve(true)
},200)
})
}
function verify2(content){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve(true)
},700)
})
}
function verify3(content){
return new Promise((resolve,reject)=>{
setTimeout(function(){
resolve(true)
},300)
})
}
Promise.all([verify1('校驗字段1的內容'),verify2('校驗字段2的內容'),verify3('校驗字段3的內容')]).then(result=>{
console.log(result)//[true, true, true]
let verifyResult = result.every(item=>item)
//驗證結果
console.log(verifyResult?'經過驗證':'未經過驗證')// 經過驗證
}).catch(err=>{
console.log(err)
})
複製代碼
語法:Promise.race(iterable)
參數: iterable 可迭代的對象,例如Array。可迭代的。
返回值: Promise.race(iterable) 方法返回一個 promise,一旦迭代器中的某個promise解決或拒絕,返回的 promise就會解決或拒絕
描述 race 函數返回一個 Promise,它將與第一個傳遞的 promise 相同的完成方式被完成。它能夠是完成( resolves),也能夠是失敗(rejects),這要取決於第一個完成的方式是兩個中的哪一個。
若是傳的迭代是空的,則返回的 promise 將永遠等待。
若是迭代包含一個或多個非承諾值和/或已解決/拒絕的承諾,則 Promise.race 將解析爲迭代中找到的第一個值。
//請求某個圖片資源
function requestImg(){
var p = new Promise(function(resolve, reject){
var img = new Image();
img.onload = function(){
resolve(img);
}
//img.src = "https://b-gold-cdn.xitu.io/v3/static/img/logo.a7995ad.svg"; 正確的
img.src = "https://b-gold-cdn.xitu.io/v3/static/img/logo.a7995ad.svg1";
});
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);
});
複製代碼
描述:有些時候,咱們前一秒刷着新聞,下一秒進入電梯後,手機頁面上就會提示你 「網絡不佳」
//請求
function request(){
return new Promise(function(resolve, reject){
setTimeout(()=>{
resolve('請求成功')
},4000)
})
}
//請求超時提醒
function timeout(){
var p = new Promise(function(resolve, reject){
setTimeout(function(){
reject('網絡不佳');
}, 3000);
});
return p;
}
Promise.race([
request(),
timeout()
])
.then(res=>{
console.log(res)
}).catch(err=>{
console.log(err)//網絡不佳
})
複製代碼
描述:相似微信小程序的登陸,首先須要 執行微信小程序的 登陸 wx.login 返回了code,而後調用後端寫的登陸接口,傳入 code ,而後返回 token ,而後每次的請求都必須攜帶 token,即下一次的請求依賴上一次請求返回的數據
function A(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('B依賴的數據')
},300)
})
}
function B(prams){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(prams + 'C依賴的數據')
},500)
})
}
function C(prams){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(prams)
},1000)
})
}
//咱們指望的是走 try ,因爲A B C模擬的請求中都是沒有reject,用 try catch 捕獲錯誤
try{
A().then( res=>B(res) ).then( res=>C(res) ).then( res=>{
console.log(res)//B依賴的數據C依賴的數據
})
} catch(e){
}
複製代碼
描述:接口返回的數據量比較大,在一個then 裏面處理 顯得臃腫,多個渲染數據分別給個then,讓其各司其職
//模擬後端返回的數據
let result = {
bannerList:[
{img:'輪播圖地址'}
//...
],
storeList:[
{name:'店鋪列表'}
//...
],
categoryList:[
{name:'分類列表'}
//...
],
//...
}
function getInfo(){
return new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve(result)
},500)
})
}
getInfo().then(res=>{
let { bannerList } = res
//渲染輪播圖
console.log(bannerList)
return res
}).then(res=>{
let { storeList } = res
//渲染店鋪列表
console.log(storeList)
return res
}).then(res=>{
let { categoryList } = res
console.log(categoryList)
//渲染分類列表
return res
})
複製代碼
參考資料:
若是你有更好的點子,歡迎留言
文中如有不許確或錯誤的地方,歡迎指出
往期文章 :