浅析 async 和 await 的用法

2022-12-19 0 454

具体来说,他们先来看一看 mdn 对 async 表达式的叙述

“async表达式是采用asyncURL新闻稿的表达式。 async表达式是AsyncFunction构造表达式的示例, 因此当中容许采用awaitURL。async和awaitURL让他们能用一类更简约的形式写下如前所述Promise的触发器犯罪行为,而无须故意地拉艾初始化promise。”

先来抽取呵呵该文中的URL即:async,[AsyncFunction](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/AsyncFunction),await,Promise ,触发器

要想更快的认知async 和 await 的用语,他们要从触发器和 Promise 开始瞄准

触发器表达式

———————————————————————————————–

触发器表达式是指透过该事件循环式触发器继续执行的表达式,它会透过两个显式的Promise 回到其结论。但假如你的标识符采用了触发器表达式,它的句法和内部结构会更像国际标准的并行表达式。

Promise

———————————————————————————————–

却是先看 mdn 文件格式:

“Promise 第一类用作则表示两个触发器操作形式的最后顺利完成 (或失利)或其结论值。”

两个 Promise 第一类代表者两个在这个 promise 被建立出时不一定未知的值。它让您能把触发器操作形式最后的获得成功codice或是失利其原因和适当的继续执行程序关连出来。 这样使触发器形式能像并行形式那般codice:触发器形式并不能立刻回到最后的值,而要会回到两个 promise,以期在今后某一这时候把值交予采用者。

两个 Promise 必定处在下列三种状况众所周知:

已确定(pending): 稳态,既没被落空,也没被婉拒。已兑现(fulfilled): 意味着操作形式获得成功顺利完成。已婉拒(rejected): 意味着操作形式失利。

接下来他们能看两个例子

function SicBo(){ return new Promise((resolve,reject) =>{ console.log(“开始摇 “) setTimeout(()=>{ let n = parseInt(Math.random()*6 + 1,10) //1~6 resolve(n) },1000) }) }

这个表达式理论上会输出两个区间为 [1,7) 的数字,让他们尝试着初始化它。

SicBo() //只会出现:”开始摇 ”

这次初始化获得成功了吗?答案当然是没,他们需要用.then来初始化它

//SicBo().then(success,fail) //then 就是然后SicBo().then( (n)=>{console.log( 的点数是+n)},//获得成功初始化获得成功表达式,失利初始化失利表达式 (y)=>{console.log( 炸了)})

.then表达式中的参数只不过是两个参数名而已,叫x,y,z什么的名字都是一样的,对应着 SicBo 表达式中的 n。由于在这个例子中不存在摇 失利的情况,所以他们先不管它。

初始化后1s后得到输出

“开始摇 ” ” 的点数是5″

async/await

———————————————————————————————–

接下来他们采用 async 和 await来重写这个例子

假如他们直接新闻稿两个 await表达式如下

function SicBo(){ … } let n = await SicBo()

这时,js就会报错,它会告诉你 await只能放在 async表达式里

浅析 async 和 await 的用法

那么他们就建立两个有async标记的表达式,然后把await放在表达式里面,就不能报错了

async function Roll(){ let n = await SicBo() }

这里出现了async/await的第两个关键知识点即:

await只能放在async表达式里面,假如不放在里面,标识符会直接报错,不能运行。

小知识:JS之父重写建立的 deno支持 let n = await 表达式名()这种写法(JS不支持)

整合呵呵标识符,这就是一个最基本的 async/await的例子,await后面接两个会return两个new Promise的表达式,并继续执行这个表达式

function SicBo(){ return new Promise((resolve,reject) =>{ console.log(“开始摇 “) setTimeout(()=>{ let n = parseInt(Math.random()*6 + 1,10) //1~6 resolve(n) },1000) }) } async function Roll(){ let n = await SicBo() //一定要写括号,不写括号就不能继续执行 new Promise console.log( 的点数是+n) } Roll() //记得要初始化表达式

在这个标识符中还需要注意的是,resolve(n)得到的结论会回到给let n = await SicBo()里面的n。在let n = await SicBo()这行标识符中,等号左边和等号右边是分离的。右边是1秒之前继续执行的,左边赋值时1s之后继续执行的,等号两边不是在同一时间继续执行的,左边要等右边继续执行完再继续执行。所以Roll表达式也是要等1s才继续执行的,所以Roll表达式是触发器的,所以function前面要加两个async,则表示它的特殊性,让引擎对它进行特殊处理,假如不标记,则报错。

try catch 捕获错误

现在加入Promise中会失利的情况 把摇 改成猜大小

function SicBo(bet){ return new Promise((resolve,reject) =>{ console.log(“开始摇 “) setTimeout(()=>{ let n = parseInt(Math.random()*6 + 1,10) //1~6 if(n>3){ if(bet === “big”){ resolve(n) //摇出是大,你也猜了大 }else{ reject(n) //摇出是大,你猜了小 } }else{ if(bet === “small”){ resolve(n) }else{ reject(n) } } },1000) }) } async function Roll(){ let n = await SicBo() //一定要写括号,不写括号就不能继续执行 new Promise console.log( 的点数是+n) } Roll()

运行标识符的这时候他们会发现只会输出“开始摇 ”,打开控制台能发现控制台报错。

浅析 async 和 await 的用法

这个错误的结论就是 的点数,显示Uncaught,所以他们要进行一段try…catch标识符。

async function Roll(){ try{ let n = await SicBo(big) //报错的话左边那一半就不能继续执行,每次都买大 console.log( 的点数是+n) console.log(你猜中了) } catch(error){ console.log( 的点数是+error) console.log(你输光了) } }

他们在一直买大的情况下,获得成功了就会输出“你猜中了”,买错了就会输出“你输光了”。

浅析 async 和 await 的用法

这时机智的你可能会发现,怎么JS里面会有try…catch呢?我这是在写Java? 我为啥要用 await和 try…catch,而不用更美观的then呢?

用 .then实现买“大”

SicBo(“大”).then(f1,f2)

那么为什么需要await呢?

答:因为要更像国际标准的并行表达式,让触发器标识符写成并行的样式,并行的标识符会更加的直观,继续执行顺序会更加明确。

.then 麻烦的地方

标识符 SicBo(“大”).then(f1,f2)中只进行了一次.then,那假如是两次或是是多次呢?

两次 Promise 的结论:

SicBo(“大”).then(f1,f2).then(f3,f4)

这这时候他们不禁要问,f3,f4什么这时候继续执行呢?

SicBo获得成功了,肯定先继续执行f1,猜错了就继续执行f2。假如f2不抛出另外的错误,依然会继续执行f3,f1不抛出另外的错误,也会继续执行f3,相反,f1或f2假如抛出错误就都会继续执行f4。

浅析 async 和 await 的用法

多重Promise的结论

浅析 async 和 await 的用法

在多重Promise的情况下,理顺表达式的继续执行顺序是相对麻烦的,所以却是那句话await让触发器标识符写成并行的样式,并行的标识符会更加的直观,继续执行顺序会更加明确

同时玩两个

在玩过几局之后,你可能已经输疯了,血压急剧飙升,迫切的想马上把本金捞回来,你可能就会上头的想同时参与两场猜大小。这次的规则是两次都猜中了,你就能获得巨额的回报,但只要两次中有一次买错了,你就血本无归了。

这时,你就会发现await的两个局限性:await只能传入两个Promise

那就先试试用promise.all能不能解决这个问题(先把async function,Roll()注释掉)

Promise.all

Promise.all([promise1, promise2]).then(success1, fail1)

特点

promise1和promise2都获得成功才会初始化success1

他们却是一直买”大”

Promise.all([SicBo(big), SicBo(big)]) .then((n)=>{console.log( 的点数是+n+你猜中了)} , (error)=>{console.log( 的点数是+error+你又输光了)})

结论如下

浅析 async 和 await 的用法

透过结论他们能很清晰的看出只有两次摇 的点数都大于3,才会输出“你猜中了”。反之只要有一次点数小于等于3,就会直接输出“你又输光了”

小结

Promise.all接受两个数组,数组里面的每个表达式都会回到两个promise,数组里面的表达式都获得成功了,才会初始化获得成功表达式,否则初始化失利表达式。

用asycn/await实现

现在他们把目光重新聚焦于asycn/await

他们之前说到await 后面永远接着两个promise,那么机智的你可能马上就能反应过来了即:Promise.all也是两个promise!

Promise.all是两个新的promise,这个promise的结论如前所述接受的数组里面的promise决定的,在摇 的例子中是如前所述两个SicBo(big)决定的,能解决多个请求(触发器)的问题

既然已经明确了Promise.all 也是两个promise,那他们就能把它放在asycn表达式里面,放在await的后面。

async function Roll(){ try{ let n/* 数组 */ = await Promise.all([SicBo(big), SicBo(big)]) console.log( 的点数是+n) console.log(你猜中了) } catch(error){ console.log(的点数是+error) console.log(你输光了) } }

效果一样,如下

浅析 async 和 await 的用法

promise.race

和Promise.all相对应得就是Promise.race。

Promise.race([promise1, promise2]).then(success1, fail1)

特点

promise1和promise2只要有两个获得成功就会初始化success1; promise1和promise2只要有两个失利就会调用fail1; 总之,谁第两个获得成功或失利,就认为是race的获得成功或失利。

Roll()的codice

———————————————————————————————–

最后 Roll()的codice是什么呢? .log呵呵,把Roll()改成下面的标识符

let result = Roll() console.log(result)
浅析 async 和 await 的用法

回到的是两个promise,再次说明了,所有async都会回到两个promise

总结

———————————————————————————————–

async/await是promise的句法糖,作用是为了让Promise更加完善,让标识符看上去更加并行

promise.all和 promise.race是为了解决多个解决(触发器的结论)

async就是为了标记 function ,其它没啥用

所有async都会回到两个promiseawait只能放在async表达式里面

郑重新闻稿

———————————————————————————————–

例子纯属玩笑,我与赌毒不共戴天!!!

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务