在开发中,异步事件是项目必然需要处理的一个环节,也因为前端框架的崛起,通过框架实现的 SPA 已是快速开发的基本了,异步获取数据也就成了不可或缺的一环。
同步?异步?
这两个名次从字面上很容易让人反过来理解
同步:指一件一件做事;
异步:很多事情同时处理;
类似过桥.同步是独木桥只能一个一个的过,异步是有多座桥,可同时过。
那么在 js 中处理异步事件的方法是什么呢?
1.回调函数
最熟悉的就是回调函数了。例如网页与用户进行互动时,就需要接收一个回调函数;如setTimeout,也都能通过传递回调函数在用户要求的时机去触发。先看例子:
在setTimeout被执行后,当过了指定的时间间隔之后,回调函数会被放到队列的末端,再等待事件处理它。
回调函数虽然在开发中十分常见,但也有许多难以避免的问题。例如最著名的“回调地狱”。
2.Promise
在 ES6 之后出现了 Promise,拯救了身陷在地狱的我们。
Promise 是通过微任务队列来驱动它的;微任务队列的触发时机是在栈被清空时,JavaScript 引擎会先确认微任务队列有没有东西,有的话就优先执行,直到清空后才从队列拿出新任务到栈上。(在HTML 5 的Web API 标准 中,Event Loop 新增了微任务队列)
上述例子setTimeout就能很好的理解微任务与一般任务的差别,同时通过.catch语法来处理异步错误
3.async/await
从 Promise 问世之后,异步代码从回调地狱逐渐变成了优雅的函数式管道处理,但对于不熟悉的开发者来说,只不过是从回调地狱变成了 Promise 地狱。
在 ES8 中规范了新的 async await,虽然只是 Promise 和 Generator Function组合在一起的语法糖,但通过 async await便可以将异步事件用同步语法来处理。
通过把 setTimeout包装成 Promise,再用 await关键字调用,可以看到结果会是同步执行的先出现 bar,再出现 foo,也就是开头提到的将异步事件写成同步处理。
在使用async/await时,由于await关键字只能在 async function 中执行,使用时务必要记得要同时使用。
另外在用循环处理异步事件时,需要注意在 ES6 之后提供的很多 Array 方法都不支持async/await语法