本篇将结合自身使用 ES6 Promise的情况,总结下Promise在我们项目开发中的常见的应用场景,当然,Promise 也许不是唯一选项,但是我们作为一个合格的前端开发人员,我们有必要了解它。
Promise.all
语法:Promise.all(iterable)
参数:一个可迭代对象,如Array。
返回值:
如果传递的iterable为空,则是已经解决的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将被异步解析/拒绝(堆栈为空时)
1. 当给定可迭代对象中的所有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] })
2..当给定可迭代对象中的任何promise被拒绝时
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.当其中有一个失败方法时,则进入失败方法;
应用场景1:多个请求结果合并在一起
思考:如果并发请求的话,每个请求的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()
应用场景2:合并请求结果并处理错误
思考:我们能否把多个请求合并在一起,哪怕有的请求失败了,也返回给我们,我们只需要在一个地方处理这些数据和错误的逻辑即可。
//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()
应用场景3:验证多个请求结果是否都是满足条件
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
语法:Promise.race(iterable)
参数: iterable 可迭代的对象,例如Array。可迭代的。
返回值:Promise.race(iterable) 方法返回一个 promise,一旦迭代器中的某个promise解决或拒绝,返回的 promise就会解决或拒绝
描述 race 函数返回一个 Promise,它将与第一个传递的 promise 相同的完成方式被完成。它可以是完成( resolves),也可以是失败(rejects),这要取决于第一个完成的方式是两个中的哪个。
如果传的迭代是空的,则返回的 promise 将永远等待。
如果迭代包含一个或多个非承诺值和/或已解决/拒绝的承诺,则 Promise.race 将解析为迭代中找到的第一个值。
应用场景1:图片请求超时
//请求某个图片资源 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); });
应用场景2:请求超时提示
//请求 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)//网络不佳 })
Promise.prototype.then
应用场景1:下个请求依赖上个请求的结果
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){ }
应用场景2:中间件功能使用
//模拟后端返回的数据 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 })
推荐教程:《JS教程》
以上就是前端 Promise 常见的一些应用场景的详细内容,更多请关注Work网其它相关文章!