前言
身为前端,一直都知道异步编程怎么用,但是都没有记录过,此系列详细介绍一下我所理解的javascript中的异步编程。
链接扩展:
异步编程之–深度理解Promise
异步编程之–理解es6的Generators(生成器 )
异步编程之–理解es6中的Iterator(迭代器)
正文
异步编程是什么?为什么要使用异步编程?
我们都知道,javascript
从诞生之日起就是一门单线程的非阻塞的脚本语言。这是由其最初的用途来决定的:与浏览器交互。
javascripty有两大特点:单线程+非阻塞
-
单线程意味着,
javascript
代码在执行的任何时候,都只有一个主线程来处理所有的任务。单线程是必要的,也是javascript
这门语言的基石,原因在其最初也是最主要的执行环境——浏览器中,我们需要进行各种各样的dom操作。 -
试想一下 如果
javascript
是多线程的,那么当两个线程同时对dom
进行一项操作,例如一个向其添加事件,而另一个删除了这个dom
,此时该如何处理呢?因此,为了保证不会 发生类似于这个例子中的情景,javascript
选择只用一个主线程来执行代码,这样就保证了程序执行的一致性。 -
现如今人们也意识到,单线程在保证了执行顺序的同时也限制了
javascript
的效率,因此开发出了web worker
技术。这项技术号称让javascript
成为一门多线程语言。 -
然而,使用
web worker
技术开的多线程有着诸多限制,例如:所有新线程都受主线程的完全控制,不能独立执行。这意味着这些“线程” 实际上应属于主线程的子线程。另外,这些子线程并没有执行I/O操作的权限,只能为主线程分担一些诸如计算等任务。所以严格来讲这些线程并没有完整的功能,也因此这项技术并非改变了javascript
语言的单线程本质。 -
单线程就好像100个人在1个售票窗口买票,而多线程就好像100个人在100个窗口买票。但是js的特点决定了不能多线程,所以衍生了单线程+非阻塞。
-
而非阻塞则是当代码需要进行一项异步任务(无法立刻返回结果,需要花一定时间才能返回的任务,如
I/O事件,ajax
)的时候,主线程会挂起(pending
)这个任务,然后在异步任务返回结果的时候再根据一定规则去执行相应的回调。 -
这种就好像:100个人去买票,车站开放了1个窗口,但是车票的预订可以在网上或其他地方完成,到车站时候只需要排队取票。我们可以看到,开1个窗口,就相当于只有1个线程。然后把耗时的一些操作分成两部分,先把快速能做完的事情做了,这样保证它不会阻塞其他代码的运行。剩下耗时的部分再单独执行。这就是单线程阻塞式的异步实现机制。