本篇将结合自身使用 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
})
复制代码
参考资料:
若是你有更好的点子,欢迎留言
文中如有不许确或错误的地方,欢迎指出
往期文章 :