javascript 异步原理

浏览器只给javascript的执行分配了一个线程,因此它是单线程的,并不能并发执行。javascript的异步处理方法并不是真正的异步,javascript异步的实现是靠事件驱动来实现的


一、在浏览器端

浏览器端的javascript实现了两个很重要的API,它们分别是定时器和ajax请求。

定时器

定时器(比如setTimeout)被执行时,由浏览器的定时器线程执行定时计数,而不是javascript执行线程负责计数。定时器线程在定时时间触发延时事件并将延时事件推入javascript事件队列。当javascript主线程同步代码执行完毕时,会去轮询该事件队列,取出最开始事件的处理函数推入主线程中执行。因此,javascript的定时器并不是准时触发的。

ajax

ajax请求和定时器一样,同样是委托浏览器线程代为执行耗时任务,这里是由浏览器的HTTP请求线程发起对服务器的请求,在请求得到响应之后触发请求完成事件,将回调函数推入事件队列等待执行。


二、NodeJS端

NodeJS的异步实现和浏览器端实现有所不同。在NodeJS中Libuv为Node.js提供了跨平台、线程池、事件池、异步I/O等能力,是Node.js如此强大的关键。Libuv 为上层的 Node.js 提供了统一的 API 调用,使其不用考虑平台差距,隐藏了底层实现。Libuv 本身就是异步和事件驱动的,所以,当我们将 I/O 操作的请求传达给 Libuv 之后,Libuv 开启线程来执行这次 I/O 调用,并在执行完成后,传回给 Javascript 进行后续处理。

总结来说,一个异步 I/O 的大致实现流程如下:

发起 I/O 调用

  1. 用户通过 Javascript 代码调用 NodeJS 核心模块,将参数和回调传入核心模块
  2. NodeJS 核心模块将传入参数和回调封装为一个请求对象
  3. 将这个请求对象推入到I/O线程池中等待执行
  4. Javascript 发起的异步调用结束,Javascript 线程继续执行后续操作

执行回调

  1. 异步任务完成之后,会将结果存放在请求对象的 result 属性上,并发出操作完成通知
  2. 每次事件循环时会检查 I/O 线程池中是否存在已经完成的 I/O 操作,如果有就将请求事件加入到I/O观察者队列当中(事件队列),之后当作事件处理
  3. 处理I/O观察者事件时,会将之前封装在请求对象中的回调函数取出,并将 result 参数传入执行,以完成 Javascript 回调的目的

javascript 异步原理_第1张图片

转载自:https://www.cnblogs.com/tianheila/p/6420587.html

你可能感兴趣的:(javascript)