其中 , 1 说明了从外部看 , task 方法执行后返回一个 Promise 对象 , 正因为它返回的是 Promise , 所以可以理解task 是一个异步方法 。 毫无疑问它是这样用的:

62说明了在 task 函数内部 , 异步已经被 “削” 成了同步 。 整个就是一个执行稍微耗时的函数而已 。
综合 1、2 , 从形式上看 , 就是 “task 整体是一个异步函数 , 内部整个是同步的” , 简称“外异内同” 。
整体是一个异步函数 不难理解 。 在实现上 , 我们不妨逆向一下 , 语言层面让async关键字调用时 , 在函数执行的末尾强制增加一个promise 反回:

7实际上 await 调用 , 是让后边的语句(函数)做了一个递归执行 , 直到获取到结果并使其 状态 变更 , 才会 resolve 掉 , 而只有 resolve 掉 , await 那一行代码才算执行完 , 才继续往下一行执行 。 所以 , 尽管外部是一个大大的 for 循环 , 但是整个 for 循环是依次串行的 。
因此 , 仅从上述框架的外观出发 , 就不难理解 async + await 的意义 。 使用起来也就这么简单 , 反而 Promise 是一个必须掌握的基础件 。
秉承本次《重读 ES6》系列的原则 , 不过多追求理解细节和具体实现过程 。 继续巩固一下这个 “形式化” 的理解 。
async + await 的进一步理解
有这样的一个异步操作 longTimeTask , 已经用 Promise 进行了包装 。 借助该函数进行一系列验证 。

8以上 2 步执行 , 清晰的证明了 exec1 函数体内是同步、逐行逐行执行的 , 即先执行完异步操作 , 然后进行 console.log() 打印 。 而 exec1() 的执行结果就直接是一个 Promise , 因为它最先会蹦出来一串 Promise ... , 然后才是 exec1 函数的内部执行日志 。
因此 , 所有验证 , 完全符合 整体是一个异步函数 , 内部整个是同步的 的总结 。
await 如何执行其后语句
回到 await , 看看它是如何执行其后边的语句的 。 假设:让 longTimeTask() 后边直接带 then() 回调 , 分两种情况:
1)then() 中不再返回任何东西2) then() 中继续手动返回另一个 promise

9longTimeTask() 加上再多得 then() 回调 , 也不过是放在了它的回调列队 queue 里了 。 也就是说 , await 命令之后始终是一条 表达式语句 , 只不过上述代码书写方式比较让人迷惑 。 (比较好的实践建议是 , 将 longTimeTask 方法身后的 then() 移入 longTimeTask 函数体封装起来)
其次 , 手动返回另一个 promise 和什么也不返回 , 关系到 longTimeTask() 方法最终 resolve 出去的内容不一样 。 换句话说 , await 命令会提取其后边的promise 的 resolve 结果 , 进而直接导致 result 的不同 。
值得强调的是 , await 命令只认 resolve 结果 , 对 reject 结果报错 。 不妨用以下的 return 语句替换上述 return 进行验证 。
猜你喜欢
- 河南人如何看郑大?网友:高一瞧之不起,高三高攀不起
- 味外之味 茶外之味 茶外之味—— 中日茶文化起点讨论杂感,乌龙茶的功效与作用
- 七里香的花语和传说,爱情的俘虏以及反战之殇
- 手工之小纸船的折法
- 祁门红茶有什么特别之处?
- 群芳之最,祁门红茶!
- 红茶之祁门红为什么这么碎?
- 莲之爱同予者何人表达了作者思想 莲之爱表达了作者怎样的感情
- 切开双眼皮,切开双眼皮恢复过程
- 如何欣赏紫砂壶的形制之美
