JS异步编程,1/3

今天整理一下JS中异步相关问题,缘起是同事的讨论。大概是三部分,1,异步是什么。2异步的语法。3异步的实现eventloop。 今天是第一部分,有以下的话题组成:

什么是异步?为什么需要异步执行?JS的语法单线程什么是异步?

异步(async)是对应同步(sync)来说的,想理解异步就要先说同步。同步执行直观的理解就是代码顺序就是执行顺序,例如:

代码的执行结果,是 A,B,C。这样,就是同步代码,执行顺序与编写顺序保持一致。

对比下面的异步代码:

代码的执行结果,是 A,C,B。编写顺序上,我们先输出的B,但是执行结果却是先输出的C。本例中, 函数就是异步执行,也就是当执行的到 时,内部的代码不会立即执行,而是将其放在异步执行队列中等待执行。同时 后边的代码就开始执行,也就是说输出C,没有等到输出B执行完,就开始执行了。

本例中, 函数就是异步执行。

为什么需要异步执行?

异步执行要解决的问题是有些非CPU密集型程序会导致CPU闲置的问题。

再看上面的例子,我将 的间隔调大到1000ms,再思考:

若输出B不是异步执行的而是同步执行的,那就意味着必须要等待1000ms,B输出完毕后,C才会输出。但是问题是,C的输出与输出B没有任何关系,同时在这1000ms内,我们除了等待,什么都没做,这就是所说的CPU被闲置。可见若没有异步执行,CPU的性能浪费是很严重的。

最常见的非CPU密集型操作,就是IO操作,无论是磁盘IO还是网络IO尤其是网络IO。在等待网络传输(或者磁盘读取)的过程中,CPU一直处于闲置状态,这个时候,就必须要让CPU运作起来,才可以充分发挥计算机性能。所以网络操作一般都是异步操作。

异步执行还有一个问题,就是若某些操作需要依赖于异步操作的结果。那如何保证这些操作的执行时机呢? JS提供了多种语法方案供我们使用,例如:事件驱动,Promise,Generator,async,await等。

JS的语法单线程

一个语法的问题需要注意,就是JS的语法层面是单线程的,就是不能同时执行。这样就带来了一个问题,就是既然是单线程的,那异步的代码是如何执行的呢?

一定要注意,单线程指的是JS的语法层面是单线程的,而不是说浏览器或Node在执行JS代码时是单线程的。

看下面的例子,说明语法层面的单线程:

上面的例子中,我们做了一个定时器,异步执行在1000ms后,之后执行一个for循环,很多次循环,执行时间大于了1000ms。从执行结果上看,当达到了1000ms时,并没有立即执行输出B,而是要等到for循环执行完毕后,才会执行已经到达时间的输出B。

这个语法现象,就是JS的语法单线程,就是执行着for的任务,不会中间停止,而是需要for任务执行完毕后,才会考虑接下来的任务!

由于上面的执行机制,出现了下面的循环的写法,目的是拆解多次的for循环,注意是使用 来实现的:

从结果上看,1000ms的计时器在时间到达时,被理立即执行,而没有被下面的循环阻塞到。因为下面的循环也是利用settimeout异步实现的。但是改代码的循环性能却大大降低,除非有非常明确的原因,否则不建议使用!

待续…

接下来:事件驱动,promise,generator,async,await,eventloop。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190221G0025400?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券