async function_如何简单理解 JavaScript 的 Async 和 Await?

文章介绍了JavaScript中Async和Await的相关知识。它们简化了同步和异步的复杂处理,async是promise的语法糖,await用于等待。还展示了利用它们实现“漂亮的等待”,并介绍了与Promise、Fetch、循环搭配使用的方法,让代码更简洁。
ef13995763a19605a942df6203b41da3.png

关注前端达人,与你共同进步

17e6873f5db13cfde59e2679abfb445b.png

文章参考来源:https://www.oxxostudio.tw/articles/201908/js-async-await.html

原文作者:oxxostudio

由于网页为繁体内容,术语描述和话术与我们有差异的问题,笔者在保证不改变原意的基础上做了调整,并在此基础上进行了错误校正,如发现问题,欢迎你的指正

开篇

自从Async 和Await 出现后,大幅简化JavaScript 同步和非同步(异步)的复杂纠葛,这篇文章将会分享我自己理解的历程,实站await 等待、连续输入文字、在循环里调用,让这些过去需要层层callback才能完成的流程,透过 Async 和 Await 轻松的进行扁平化处理吧!

01

什么是async?什么是await?

在JavaScript的世界,同步sync和非同步async的爱恨情仇,就如同偶像剧一般的剪不断理还乱,特别像是setTimeout、setInterval、MLHttpRequest或fetch这些同步非同步混杂的用法,都会让人一个头两个大,幸好ES6出现了promise,ES7出现了async、await,帮助我们可以更容易的进行业务逻辑的编写。

对于同步和非同步,最常见的说法是「同步模式下,每个任务必须按照顺序执行,后面的任务必须等待前面的任务执行完成,非同步模式则相反,后面的任务不用等前面的,各自执行各自的任务」,但我觉得这样实在不容易理解,不容易理解的地方在于「中文」的同步和非同步,可能和实际上的解释刚好相反了(同步的中文字面意思是「一起走」,非同步的中文意思是「不要一起走」,超容易搞错的),因此如果你跟我一样也很容易搞错,可以使用我觉得比较好理解的方法:「同一个赛道vs不同赛道」,透过赛道的方式,就更容易明白同步和非同步。

同步:在「同一个赛道」比赛「接力赛跑」,当棒子没有交给我,我就得等你,不能跑。

非同步:在「不(非)同赛道」比赛「赛跑」,谁都不等谁,只要轮到我跑,我就开始跑。

baf70f4d1949b28c81a6f152457362b1.png

在ES7里头 async 的本质是 promise 的语法糖(包装得甜甜的比较好吃下肚),只要 function标记为 async,就表示里头可以编写 await 的同步语法,而 await 顾名思义就是「等待」,它会确保一个 promise 的内容都解决( resolve )或出错( reject )后才会进行下一步,当 async function 的内容全都结束后,会返回一个 promise ,这表示后方可以使用 .then 语法来做连接,基本的代码长相就像下面这样:

9cb4cc5112c1d0fc430d01ecb108dc2b.png

02

利用async 和 await 做个「漂亮的等待」

了解 async 和 await 的意思之后,就来试试看做个「漂亮的等待」:

b9353c6ba5a034b14e25c7b4cd0c2618.png

如果我们把上面的范例修改为 async 和 await 的写法,突然就发现代码看起来非常的干净,因为 await 会等待收到 resolve 之后才会进行后面的动作,如果没有收到就会一直处在等待的状态,所以什么时候该等待,什么时候该做下一步,就会非常清楚明了,这也就是我所谓「漂亮的等待」。

注意,await 一定得运行在async function 内!

133dc4e36f6cb28212b5f78e32d9f2f0.png

03

搭配Promise

基本上只要有 async 和 await 的地方,就一定有 promise 的存在,promise 顾名思义就是「保证执行之后才会做什么事情」,刚刚使用了 async 、await 和 promise 改善 setTimeout这个容易出错的非同步等待,针对 setInterval ,也能用同样的做法修改,举例来说,下面的代码码执行之后,并「不会」如我们预期的「先显示1,再显示 haha0...haha5 ,最后再显示2」,而是「先显示1和2,然后再出现 haha0...haha5」,因为虽然代码逻辑是从上往下,但在count function里头是非同步的语法,导致自己走自己的路,也造成了结果的不如预期。

6e3b3fd459ecd292677f82c69660a7f1.png

我们可以透过 async、await 和 promise 进行修正,在显示1之后,会「等待」count function结束后再显示2。

f00ea83a230c3c6a6457988520d8e324.png

setTimeout 和 setInterval ,这也可以应用于「输入文字」的场景,过去我们要做到「连续输入」文字,可能要层层叠叠写个好几个callback,现在如果使用async和await,就能够很简单的实现连续输入的情境,程式码看起来也更干净简洁。

html结构:

f8976b1ea988c4feb2dae5c9ba240147.png

js代码:

d32e052a6878ef51d3ee7347a6a9e499.png

运行效果:

1603cd796b8e8f810dcc299df984bcb8.gif

insertAdjacentHTML() 将指定的文本解析为HTML或XML,并将结果节点插入到DOM树中的指定位置。它不会重新解析它正在使用的元素,因此它不会破坏元素内的现有元素。这避免了额外的序列化步骤,使其比直接innerHTML操作更快。

04

搭配Fetch

在上篇的文章 JavaScript Fetch API 使用教学已经有提到 fetch 的用法,因为 fetch 最后回传的是promise,理所当然的通过 async 和await 操作是最恰当不过的。

举例来说,先前往类似阿里云的获取天气 API 的平台可以取得许多气象资料,搜索某个城市的现在天气报告,通过 fetch的json() 方法处理返回数据,结果显示出「北京市的即时气温」。

透过 async 和 await 的简化代码,得到的结果完全不需要 callback 的辅助,就能按照我们所期望的顺序进行。( 先显示「开始调用API」,接着显示「北京市的气温」,最后显示「气温结果」 )

c7dd23fbd2c2f53e3f1257edeb54d24f.png

05

搭配循环

如果要通过 JavaScript 实现「文字慢慢变大」的效果,除了通过CSS的 transition 这个属性之外,通常就是直接使用 setInterval 来完成,就像下面的代码这样:

b6ae7a912a06f3bb2979583da8fc73b2.png

搭配async 和await,我们就能将同样的做法,因为使用了await,所以每次执行时,都会进行「等待」,也就能做到字体慢慢变大的效果。

html结构:

5692b056483799308524c36382e1dcf6.png

js代码:

751750d7e475ab284a294f9ce5123921.png

运行效果:

b2c06190192c0d6dceb7a4b3cb603230.gif

同样的,上面提到的fetch 或是输入文字,只要做成await 的方式,都可以放在循环里面使用,例如通过循环使用 fetch 方法调用接口数据、通过循环调用输入文字的方法...等,这些就不是callback 方法能容易办到的啰~

e89040ff51d7e53ad9d5407f66de239a.gif

坦白说只要你一但熟悉了async 和await,就真的回不去了,虽然说callback 仍然我们开发中会用到,但对于同步和非同步之间的转换,以后就交给 async 和await来处理吧!

简单了解之后,如果你想深入学习的话,笔者建议你看看我以前写的两篇文章:「JavaScript基础」Promise使用指南、「JavaScript基础」深入学习async/await,相信你看完后会有不小的收获。

精彩推荐

js基础丨JavaScript Fetch API 新手入门指南

React TS3丨亲自动手创建一个类组件(class component)

React TS3 丨从创建第一个 React TypeScript3 项目开始

css基础丨你想知道的伪元素内容都在这篇文章里(长文值得收藏)

css基础丨一次搞懂CSS 字体单位:px、em、rem 和 %

css基础丨只用1个div,你能用CSS常规属性绘制:正3、4、5、6、7、8边形吗?

CSS 3D 专题丨搞懂 CSS 3D,你必须理解 perspective(视域)这个属性

JS基础丨Array 数组操作方法大全( 含ES6 )

JS小技巧丨随机不重复的ID,模板标签替换,XML与字符串互转,快速取整

CSS 3D 专题丨学习前,你需要搞明白什么是CSS 3D?

css实用手册丨CSS 垂直居中的七种方法,值得收藏

Web Animation API丨用原生JS制作一个图片随机移动的动画

十款热门的Vue.js工具和库

vue基础丨新手入门篇(一)

小技巧丨console的用法,不仅仅只有console.log()

动画基础丨点和直线

太惊艳了,这些画都是CSS的杰作!

css基础丨Transforms 属性在实际项目中如何应用?

css基础丨如何理解transform的matrix()用法

css基础丨如何理解Display的属性:None,Block,Inline,Inline-Block

ES6基础丨let和作用域

ES6基础丨const介绍

ES6基础丨默认参数值

ES6基础丨展开语法(Spread syntax)

ES6基础丨解构赋值(destructuring assignment)

ES6基础丨箭头函数(Arrow functions)

ES6基础丨模板字符串(Template String)

ES6基础丨Set与WeakSet

ES6基础丨Map与WeakMap

ES6基础丨Symbol介绍:独一无二的值

ES6基础丨Object的新方法

ES6基础丨迭代器(iterator)

ES6基础丨生成器(Generator)

ES6基础丨你需要知道的Array数组新方法(上)

数据结构基础丨栈简介(使用ES6)

数据结构基础丨队列简介(使用ES6)

JavaScript基础丨前端不懂它,会再多框架也不过只是会用而已!

JavaScript基础丨你真的了解JavaScript吗?

JavaScript基础丨回调(callback)是什么?

JavaScript基础丨Promise使用指南

JavaScript基础丨深入学习async/await

JS加载慢?谷歌大神带你飞!(文末送电子书)

19年你应该关注这50款前端热门工具(上)

19年你应该关注这50款前端热门工具(中)

19年你应该关注这50款前端热门工具(下)

专注分享当下最实用的前端技术。关注前端达人,与达人一起学习进步!

长按关注"前端达人"

c6440df04c0f64ba575105379aa6de24.gif86eb633d429ad891b34055d1e64c6ffa.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值