一、JS里的同步异步
fun1(); fun2(); fun3();
如以上代码,在同步情况下三个函数应该是依次执行的,fun1执行完执行fun2,最终执行fun3。
什么是异步呢?异步就是大家各做各的,互不干扰,无需互相等待。
但需注意,各做各的,并不意味着乱序。它依然是顺序执行的。只不过,fun1没执行完,fun2已经开始执行了。
JS里的常见异步函数有:settimeout、fetch、setInterval等。
二、Promise
Promise中文意思是承诺,在JS中,可以通俗理解为:把这个任务(函数)交给我,我来完成。
1、状态
Promise 的三种状态:pending(等待中)、fulfilled(成功)、rejected(失败),且状态改变是不可逆的。
const p=new Promise((resolve,reject)=>{ resolve("你的成功结果") //执行更改后Promise状态变成fulfilled //reject("失败的结果") //执行更改后Promise状态变成rejected //throw 1 //抛出异常和reject的效果一样 }) p.then(res=>res) //then直接返回会返回包含返回结果的Promise对象,可以通过.then()继续获取 .then(res=>{ //res对应resolve里的值 console.log("fulfilled状态时打印") //以下执行可以返回状态为rejected的Promise给下一级继续执行 return new Promise((resolve,reject)=>reject("执行出错")) }).catch(error=>{ //error对应reject里的内容 console.log("rejected状态时打印") }).finally(()=>{ console.log("无论成功还是失败都会打印") })
2、all()、race()、any()
先一句话描述以下Promise.all()、Promise.race()、Promise.any()的区别:
(1) Promise.all() 中的Promise序列会全部执行通过才认为是成功,否则认为是失败;
(2) Promise.race() 中Promise序列中第一个执行完毕的是通过,则认为是成功,如果第一个执行完毕的Promise是rejected,则认为失败;
(3) Promise.any() 中Promise序列只有有一个执行通过,则认为成功,如果全部拒绝,则认为失败。
用一张图来说明all()、any():
any和all类似,区别在于any只要有一个成功就返回成功的结果。
用一张图来说明race():
Both resolve, but promise2 is faster ,从这里可以看出端倪。顾名思义,Promse.race 就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。
3、简单案例
通过简单案例了解:
//Promise用法 const param1 = "normal"; const param2 = "error"; // 第二种情况 //1. 创建Promise类的对象 const promise01 = new Promise(function customFun(successFun, failFun) { if (param1 === "normal") { successFun("自定义成功的函数执行了!") } else { //失败和成功的逻辑都是自定义的 failFun("自定义失败的函数执行了!") } }) const promise02 = new Promise(function customFun(successFun, failFun) { // 第二种情况 if (param2 === "normal") { successFun("自定义成功的函数执行了!") } else { //失败和成功的逻辑都是自定义的 failFun("自定义失败的函数执行了!") } }) //2. 执行Promise的返回结果 promise01.then(result => { console.log(result) }).catch(error => { console.log(error) }) promise02.then(result => { // 第二种情况 console.log(result) }).catch(error => { console.log(error) })
可以看到控制台打印如下:
第一种情况走自定义成功的逻辑,第二种情况走自定义失败的逻辑。
4、异步执行案例
//异步常见案例 const promise03 = new Promise(() => { console.log("This is Promise constructor.") setTimeout(() => { console.log("Timeout executed!") }, 3000) }) promise03.then(result => { console.log(result) }) console.log("Test Demo.")
控制台输出:
可以清晰地看到,在Promise被执行时,构造信息就已经打印了,之后,顺序执行了Test Demo, 等待3秒后系统再执行了setTimout里的逻辑。
5、解决异步嵌套繁琐的场景
//Promise来规范Timeout嵌套调用的阅读性差问题 const promise04 = new Promise((successFun, failFun) => { setTimeout(() => { successFun("timeout 333") }, 3000) }) const promise05 = promise04.then((res) => { console.log(res) return new Promise((successFun, failFun) => { setTimeout(() => { successFun("timeout 222") }, 2000) }) }) promise05.then(res => { console.log(res) }) console.log("Test Demo.")
控制台打印:
可以看到,首先打印了Test Demo,3秒后执行了第一各Promise里的内容,执行完第一个Promise里的内容后,再过2秒执行了第二各Promise里的内容。这比setTimout的多层嵌套,可读性更好。
三、async和await
async必须用来修饰函数,用来表示该函数是一个异步函数,await必须和async配套使用。await专门用来修饰Promise的实例化对象。
1、async返回类型
//async有返回类型时,以Promise形式返回 async function asyncDemo01Fun(){ return "Demo01" } async function asyncDemo02Fun(){ return Promise.resolve("Demo02") } console.log(asyncDemo01Fun()) console.log(asyncDemo02Fun())
打印结果:
可以看到,直接返回结果和利用Promise.resolve返回结果是一样的。
由async修饰的函数,在有返回值时都会直接返回Promise对象,而非直接返回值。
2、async与await结合使用的简单案例
//async和await的案例Demo async function asyncFun1() { const p = new Promise((successFun, failFun) => { setTimeout(() => { successFun({num: 1}) }, 3000) }) let obj = await p; console.log(obj) } asyncFun1() console.log("Test Demo.")
打印结果:
可以看到,当有await修饰Promise返回对象时,会等待Promise对象执行完成后,再返回结果给对象,最终将获取到的对象值在3秒后打印。
当有await修饰Promise对象时,系统会等待返回值后再返回对象,继续执行。实际上是将异步处理的事件处理完成后再继续执行同步代码。
3、解决异步嵌套问题
//async和await的案例Demo async function asyncFun2() { const p1 = new Promise((successFun, failFun) => { setTimeout(() => { successFun("Demo 333") }, 3000) }) let obj1 = await p1; console.log(obj1) const p2 = new Promise((successFun, failFun) => { setTimeout(() => { successFun("Demo 222") }, 2000) }) let obj2 = await p2; console.log(obj2) } asyncFun2() console.log("Test Demo.")
控制台打印:
可以看到,首先打印了Test Demo,3秒后执行了第一各Promise里的内容,执行完第一个Promise里的内容后,再过2秒执行了第二各Promise里的内容。这比setTimout的多层嵌套,可读性更好。
4、批量请求优化
以下是同步获取请求结果的案例:
const batchReq=async ()=>{ const url="https://example.com/api/demo" let rep1=await fetch(`${url}/1/`) let json1=await rep1.json() let name1=await json1.data.name let rep2=await fetch(`${url}/2/`) let json2=await rep1.json() let name2=await json1.data.name let rep3=await fetch(`${url}/3/`) let json3=await rep1.json() let name3=await json1.data.name console.log(name1) console.log(name2) console.log(name3) }
以上代码在执行的过程中,由于加了await进行修饰,会依次进行请求,1执行完2执行最后3执行。
如要实现批量请求同时处理,可以参考以下代码:
const batchReq = async () => { try { const url = "https://example.com/api/demo" let resp = await Promise.all([fetch(`${url}/1/`), fetch(`${url}/2/`), fetch(`${url}/3/`)]) let jsons = resp.map(res => res.json()) let values = await Promise.all(jsons) values.map(value => { console.log(value.data.name) }) } catch (error) { console.log(error) } }
这样写便可以批量发送请求了。
总结
到此这篇关于JavaScript异步Promise、Async、await使用的文章就介绍到这了,更多相关JS异步Promise、Async、await内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
来源链接:https://www.jb51.net/javascript/339345s3b.htm
如有侵犯您的版权,请及时联系3500663466#qq.com(#换@),我们将第一时间删除本站数据。
暂无评论内容