图解 Google V8 # 17:消息队列:V8是怎么实现回调函数的?

简介: 图解 Google V8 # 17:消息队列:V8是怎么实现回调函数的?

说明

图解 Google V8 学习笔记



什么是回调函数?


只有当某个函数被作为参数,传递给另外一个函数,或者传递给宿主环境,然后该函数在函数内部或者在宿主环境中被调用,才称为回调函数


回调函数有两种不同的形式:

  • 同步回调:函数在执行函数内部被执行的;
  • 异步回调:函数在执行函数外部被执行的。



UI 线程的宏观架构


注意:在浏览器的页面里面是UI线程,node中就是它的主线程。


什么是 UI 线程?

所谓 UI 线程,是指运行窗口的线程,当你运行一个窗口时,无论该页面是 Windows 上的窗口系统,还是 Android 或者 iOS 上的窗口系统,它们都需要处理各种事件,诸如有触发绘制页面的事件,有鼠标点击、拖拽、放大缩小的事件,有资源下载、文件读写的事件,等等。


748561bafc394d10a4cdc69eaccc6bb3.png


通用的 UI 线程的结构,有消息队列,通过鼠标、键盘、触控板等产生的消息都会被添加进消息队列,主线程会循环地从消息队列中取出消息并执行。


异步回调函数的调用时机


异步回调有两种不同的类型,其典型代表是 setTimeout 和 XMLHttpRequest。


setTimeout

例子:比如在页面主线程中正在执行 A 任务,在执行 A 任务的过程中调用 setTimeout(foo, 3000)


function foo() {
    alert("Hello");
}
setTimeout(foo, 3000)


示意图:

c24dce610b87414b8012c4623efc23a6.png



在执行 setTimeout 函数的过程中,宿主就会将 foo 函数封装成一个事件,并添加到消息队列中,然后 setTimeout 函数执行结束。主线程会不间断地从消息队列中取出新的任务,执行新的任务,等到时机合适,便取出 setTimeout 设置的 foo 函数的回调的任务,然后就可以直接执行 foo 函数的调用。

定时器有单独的队列,每次执行新的宏任务时,主线程会先在这两个队列中查找即将要执行的事件,然后执行。


xmlHttpRequest


XMLHttpRequest 是用来下载网络资源的,而下载任务会消耗比较久,如果在 UI 线程上执行,会阻塞 UI 线程,拖慢 UI 界面的交互和绘制的效果。所以当主线程从消息队列中取出来了这类下载任务之后,会将其分配给网络线程。


示意图:


72b61622da87482c9b20d5f55af98489.png



XMLHttpRequest 所触发的回调流程:


   UI 线程会从消息队列中取出一个任务,并分析该任务。


   分析过程中发现该任务是一个下载请求,那么主线程就会将该任务交给网络线程去执行。


   网络线程接到请求之后,便会和服务器端建立连接,并发出下载请求;


   网络线程不断地收到服务器端传过来的数据;


   网络线程每次接收到数据时,都会将设置的回调函数和返回的数据信息,如大小、返回了多少字节、返回的数据在内存中存放的位置等信息封装成一个新的事件,并将该事件放到消息队列中 ;


   UI 线程继续循环地读取消息队列中的事件,如果是下载状态的事件,那么 UI 线程会执行回调函数,程序员便可以在回调函数内部编写更新下载进度的状态的代码;


   直到最后接收到下载结束事件,UI 线程会显示该页面下载完成。


网络线程在执行下载的过程中,会将一些中间信息和回调函数封装成新的消息,并将其添加进消息队列中,然后主线程从消息队列中取出回调事件,并执行回调函数。










目录
相关文章
|
Web App开发 缓存 JavaScript
图解 Google V8 # 13:字节码(一):V8为什么又重新引入字节码?
图解 Google V8 # 13:字节码(一):V8为什么又重新引入字节码?
236 0
图解 Google V8 # 13:字节码(一):V8为什么又重新引入字节码?
|
缓存 JavaScript 前端开发
图解 Google V8 # 22 :关于内存泄漏、内存膨胀、频繁垃圾回收的解决策略(完结篇)
图解 Google V8 # 22 :关于内存泄漏、内存膨胀、频繁垃圾回收的解决策略(完结篇)
307 0
图解 Google V8 # 22 :关于内存泄漏、内存膨胀、频繁垃圾回收的解决策略(完结篇)
|
Web App开发 JavaScript 前端开发
图解 Google V8 # 21 :垃圾回收(二):V8是如何优化垃圾回收器执行效率的?
图解 Google V8 # 21 :垃圾回收(二):V8是如何优化垃圾回收器执行效率的?
118 0
图解 Google V8 # 21 :垃圾回收(二):V8是如何优化垃圾回收器执行效率的?
|
算法 JavaScript Java
图解 Google V8 # 20 :垃圾回收(一):V8的两个垃圾回收器是如何工作的?
图解 Google V8 # 20 :垃圾回收(一):V8的两个垃圾回收器是如何工作的?
102 0
图解 Google V8 # 20 :垃圾回收(一):V8的两个垃圾回收器是如何工作的?
|
前端开发 JavaScript
图解 Google V8 # 19 :异步编程(二):V8 是如何实现 async/await 的?
图解 Google V8 # 19 :异步编程(二):V8 是如何实现 async/await 的?
132 0
图解 Google V8 # 19 :异步编程(二):V8 是如何实现 async/await 的?
|
消息中间件 前端开发 JavaScript
图解 Google V8 # 18 :异步编程(一):V8是如何实现微任务的?
图解 Google V8 # 18 :异步编程(一):V8是如何实现微任务的?
422 0
图解 Google V8 # 18 :异步编程(一):V8是如何实现微任务的?
|
存储 缓存 索引
图解 Google V8 # 16:V8是怎么通过内联缓存来提升函数执行效率的?
图解 Google V8 # 16:V8是怎么通过内联缓存来提升函数执行效率的?
145 0
图解 Google V8 # 16:V8是怎么通过内联缓存来提升函数执行效率的?
|
JavaScript 前端开发 编译器
图解 Google V8 # 15:隐藏类:如何在内存中快速查找对象属性?
图解 Google V8 # 15:隐藏类:如何在内存中快速查找对象属性?
140 0
图解 Google V8 # 15:隐藏类:如何在内存中快速查找对象属性?
|
JavaScript 前端开发 Java
图解 Google V8 # 14:字节码(二):解释器是如何解释执行字节码的?
图解 Google V8 # 14:字节码(二):解释器是如何解释执行字节码的?
242 0
图解 Google V8 # 14:字节码(二):解释器是如何解释执行字节码的?
|
2月前
|
数据可视化 定位技术 Sentinel
如何用Google Earth Engine快速、大量下载遥感影像数据?
【2月更文挑战第9天】本文介绍在谷歌地球引擎(Google Earth Engine,GEE)中,批量下载指定时间范围、空间范围的遥感影像数据(包括Landsat、Sentinel等)的方法~
1166 1
如何用Google Earth Engine快速、大量下载遥感影像数据?

热门文章

最新文章