Heim > Web-Frontend > js-Tutorial > Hauptteil

前端 Promise 常见的一些应用场景

hzc
Freigeben: 2020-06-15 10:08:31
nach vorne
4195 人浏览过

本篇将结合自身使用 ES6 Promise的情况,总结下Promise在我们项目开发中的常见的应用场景,当然,Promise 也许不是唯一选项,但是我们作为一个合格的前端开发人员,我们有必要了解它。

Promise.all


语法:Promise.all(iterable)

参数:一个可迭代对象,如Array。

返回值:

  • 如果传递的iterable为空,则是已经解决的Promise。

Promise.all([]).then(res=>{
    console.log(res)//[]
})
Nach dem Login kopieren
  • 异步解析的Promise(如果传递的Iterable不包含Promise)。 请注意,在这种情况下,Google Chrome 58返回已解决的承诺。

Promise.all([1,2,3]).then(res=>{
    console.log(res)//[1,2,3]
})
Nach dem Login kopieren
  • 当给定可迭代对象中的所有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]
})
Nach dem Login kopieren

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
})
Nach dem Login kopieren

描述:

此方法对于汇总多个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()
Nach dem Login kopieren

应用场景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()
Nach dem Login kopieren

有时候页面挂掉了,可能因为接口异常导致,或许只是一个无关紧要的接口挂掉了。那么一个接口挂掉了为什么会导致整个页面无数据呢?Promise.all告诉我们,如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),就不再执行then方法回调,以上用例 正好可以解决此种问题

应用场景3:验证多个请求结果是否都是满足条件

描述:在一个微信小程序项目中,做一个表单的输入内容安全验证,调用的是云函数写的方法,表单有多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)
})
Nach dem Login kopieren

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);
});
Nach dem Login kopieren

应用场景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)//网络不佳
})
Nach dem Login kopieren

Promise.prototype.then


应用场景1:下个请求依赖上个请求的结果

描述:类似微信小程序的登录,首先需要 执行微信小程序的 登录 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){
    
}
Nach dem Login kopieren

应用场景2:中间件功能使用

描述:接口返回的数据量比较大,在一个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
})
Nach dem Login kopieren

推荐教程:《JS教程

以上是前端 Promise 常见的一些应用场景的详细内容。更多信息请关注PHP中文网其他相关文章!

Verwandte Etiketten:
Quelle:juejin.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!