01-异步编程
第14章 异步编程
在第1章响应用户交互的时候我们第一次见到了异步编程。回忆一下用户交互,它本质上是一个异步:因为无法控制用户的点击、触摸、说话或者敲击等事件。不过,用户输入并不是需要执行异步编程的唯一原因:在JavaScript中,很多东西本质上都是由异步编程实现的。
当一个JavaScript应用在运行的时候,它会以单线程的方式运行。也就是说,JavaScript在同一个时刻只做一件事。大部分现代计算机都可以同时处理多件事情(假设它们是多核的),即使是单核计算机,也因为具有极高的运算速度从而可以模拟同时处理多件事,它会先处理一部分A任务,然后处理一部分B任务,再处理一部分C任务,如此循环直到所有任务都处理完(也叫抢占式多任务处理)。对于用户来说,任务A、B、C是同时运行的,不管它们是否真的在多个内核中同步进行。
JavaScript的单线程性质可能会让开发人员觉得被限制了,但实际上它避免了开发人员为多线程编程中可能出现的棘手问题而担心。不过这种自由是有条件的:为了写出能够流畅运行的软件,必须考虑异步,而不仅仅是用户输入。这种思考方式刚开始可能会有些困难,尤其是在之前使用的编程语言都是同步执行的情况下。
JavaScript这门编程语言从早期开始就有一套自己的异步执行方式。不过,随着JavaScript的普及,它所能完成的软件也越来越复杂,一些管理异步编程的新理念也被吸收进这门语言中。就事实而言,JavaScript对异步编程的支持有三个不同的阶段:回调(callback)阶段、promise(承诺)阶段和生成器(generator)阶段。如果只是简单地说生成器比任何出现在它之前的阶段都好,那么只了释生成器的工作原理,而跳过其他的就好。但实际上并不是这么简单。生成器本身并不提供任何对异步的支持:它们依赖于承诺或特定类型的回调来提供异步行为。同样,像承诺这样有用的东西,会依赖于回调(而回调本身又由于具有对象而变得更有用)。
除了用户输入以外,异步编程技术的三个主要使用场景是:
- 网络请求(如Ajax请求)。
- 文件系统操作(读/写文件等)。
- 刻意的时间延迟功能(比如警告)。