几种实用的JavaScript鼠标特效,在我们平时网页设计中,鼠标特效可以说是常常会用到,那么今天我们来讲讲通过JS代码实现一些实用的鼠标特效,希望对大家有用。......
2023-03-17 528 JAVASCRIPT 鼠标
异步编程一直是JavaScript 编程的重大事项。关于异步方案, ES6 先是出现了 基于状态管理的 Promise,然后出现了 Generator 函数 co 函数,紧接着又出现了 ES7 的 async await 方案。
本文力求以最简明的方式来疏通 async await。
异步编程的几个场景
先从一个常见问题开始:一个for 循环中,如何异步的打印迭代顺序
用闭包或者ES6 规定的 let 块级作用域来回答这个问题。
这里描述的是一个均匀发生的的异步,被依次按既定的顺序排在异步队列中等待执行。
如果异步不是均匀发生的,那么被注册在异步队列中的顺序就是乱序的。
返回的结果是乱序不可控的,这本来就是最为真实的异步。另一种情况是,在循环中,如果希望前一个异步执行完毕、后一个异步再执行,该怎么办?
这不就是多个异步 “串行”
在回调 callback 嵌套异步操作、再回调的方式,不就解决了这个问题!或者,使用 Promise then() 层层嵌套同样也能解决问题。但是,如果硬是要将这种嵌套的方式写在循环中,还恐怕还需费一番周折。
异步同步化方案
如果要去将一批数据发送到服务器,只有前一批发送成功(即服务器返回成功的响应),才开始下一批数据的发送,否则终止发送。这就是一个典型的 “for 循环中存在相互依赖的异步操作” 的例子。
明显,这种 “串行” 的异步,实质上可以当成同步。它和乱序的异步比较起来,花费了更多的时间。按理说,我们希望程序异步执行,就是为了 “跳过” 阻塞,较少时间花销。但与之相反的是,如果需要一系列的异步 “串行”,我们应该怎样很好的进行编程?
对于这个 “串行” 异步,有了 ES6 就非常容易的解决了这个问题。
本次循环,等有了结果,再进行下一次循环。因此,循环每执行一次就会被暂停(“卡住”)一次,直到循环结束。这种编码实现,很好的消除了层层嵌套的 “回调地狱” 问题,降低了认知难度。
这就是异步问题同步化的方案。如果说 Promise 主要解决的是异步回调问题,那么 async await 主要解决的就是将异步问题同步化,降低异步编程的认知负担。
async await “外异内同”
早先接触这套 API 时,看着繁琐的文档,一知半解的认为 async await 主要用来解决异步问题同步化的。
其实不然。从上面的例子看到:async 关键字声明了一个 异步函数,这个 异步函数 体内有一行 await 语句,它告示了该行为同步执行,并且与上下相邻的代码是依次逐行执行的。
将这个形式化的东西再翻译一下,就是:
1、async 函数执行后,总是返回了一个 promise 对象2、await 所在的那一行语句是同步的
其中,1 说明了从外部看,task 方法执行后返回一个 Promise 对象,正因为它返回的是 Promise,所以可以理解task 是一个异步方法。毫无疑问它是这样用的:
2说明了在 task 函数内部,异步已经被 “削” 成了同步。整个就是一个执行稍微耗时的函数而已。
综合 1、2,从形式上看,就是 “task 整体是一个异步函数,内部整个是同步的”,简称“外异内同”。
整体是一个异步函数 不难理解。在实现上,我们不妨逆向一下,语言层面让async关键字调用时,在函数执行的末尾强制增加一个promise 反回:
实际上 await 调用,是让后边的语句(函数)做了一个递归执行,直到获取到结果并使其 状态 变更,才会 resolve 掉,而只有 resolve 掉,await 那一行代码才算执行完,才继续往下一行执行。所以,尽管外部是一个大大的 for 循环,但是整个 for 循环是依次串行的。
因此,仅从上述框架的外观出发,就不难理解 async await 的意义。使用起来也就这么简单,反而 Promise 是一个必须掌握的基础件。
秉承本次《重读 ES6》系列的原则,不过多追求理解细节和具体实现过程。继续巩固一下这个 “形式化” 的理解。
async await 的进一步理解
有这样的一个异步操作 longTimeTask,已经用 Promise 进行了包装。借助该函数进行一系列验证。
以上 2 步执行,清晰的证明了 exec1 函数体内是同步、逐行逐行执行的,即先执行完异步操作,然后进行 console.log() 打印。而 exec1() 的执行结果就直接是一个 Promise,因为它最先会蹦出来一串 Promise ...,然后才是 exec1 函数的内部执行日志。
因此,所有验证,完全符合 整体是一个异步函数,内部整个是同步的 的总结。
await 如何执行其后语句
回到 await ,看看它是如何执行其后边的语句的。假设:让 longTimeTask() 后边直接带 then() 回调,分两种情况:
1)then() 中不再返回任何东西2) then() 中继续手动返回另一个 promise
longTimeTask() 加上再多得 then() 回调,也不过是放在了它的回调列队 queue 里了。也就是说,await 命令之后始终是一条 表达式语句,只不过上述代码书写方式比较让人迷惑。(比较好的实践建议是,将 longTimeTask 方法身后的 then() 移入 longTimeTask 函数体封装起来)
其次,手动返回另一个 promise 和什么也不返回,关系到 longTimeTask() 方法最终 resolve 出去的内容不一样。换句话说,await 命令会提取其后边的promise 的 resolve 结果,进而直接导致 result 的不同。
值得强调的是,await 命令只认 resolve 结果,对 reject 结果报错。不妨用以下的 return 语句替换上述 return 进行验证。
以上方法由办公区教程网编辑摘抄自百度经验可供大家参考!
标签: JAVASCRIPT
相关文章
几种实用的JavaScript鼠标特效,在我们平时网页设计中,鼠标特效可以说是常常会用到,那么今天我们来讲讲通过JS代码实现一些实用的鼠标特效,希望对大家有用。......
2023-03-17 528 JAVASCRIPT 鼠标
如何开始学习javascript,html是网页的内容,c是网页的格式,h是网站的后台,j是网站的前端,那么如何学习j,才能高效?......
2023-03-17 256 JAVASCRIPT