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


    说明

    图解 Google V8 学习笔记

    什么是回调函数?

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

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

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

    UI 线程的宏观架构

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

    什么是 UI 线程?

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

    消息队列解决了什么问题?

    早期其实只有一个 UI 线程,js 的执行也是在 UI 线程中,那么,鼠标的各种事件,例如鼠标移动事件,每移动一像素就会触发一次事件,很显然,UI 线程是无法及时响应和处理这些事件的,所以消息队列的出现就是为了解决这个问题的。UI 线程会将这些待执行的事件添加到消息队列中,然后 UI 线程会不断循环地从消息队列中取出事件、执行事件。直到队列为空,当前 UI 线程也会被挂起。

    通用 UI 线程架构

    UI 线程每次从消息队列中取出事件,执行事件的过程称为一个任务。

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

    异步回调函数的调用时机

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

    setTimeout

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

    function foo() {
        alert("Hello");
    }
    setTimeout(foo, 3000)
    
    • 1
    • 2
    • 3
    • 4

    示意图:

    在这里插入图片描述

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

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

    xmlHttpRequest

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

    示意图:

    在这里插入图片描述

    XMLHttpRequest 所触发的回调流程:

    1. UI 线程会从消息队列中取出一个任务,并分析该任务。
    2. 分析过程中发现该任务是一个下载请求,那么主线程就会将该任务交给网络线程去执行。
    3. 网络线程接到请求之后,便会和服务器端建立连接,并发出下载请求;
    4. 网络线程不断地收到服务器端传过来的数据;
    5. 网络线程每次接收到数据时,都会将设置的回调函数和返回的数据信息,如大小、返回了多少字节、返回的数据在内存中存放的位置等信息封装成一个新的事件,并将该事件放到消息队列中 ;
    6. UI 线程继续循环地读取消息队列中的事件,如果是下载状态的事件,那么 UI 线程会执行回调函数,程序员便可以在回调函数内部编写更新下载进度的状态的代码;
    7. 直到最后接收到下载结束事件,UI 线程会显示该页面下载完成。

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

  • 相关阅读:
    2022 12 3
    colab切换目录的解决方案
    【电路笔记】-节点电压分析和网状电流分析
    Day1 数据分析 关系数据库和MySQL【中级】
    白盒子测试总结
    Linux文本编辑器---vim详解
    如何使用界面控件Telerik UI for WinForms过滤数据?这里有答案
    CAN通信
    认证服务(keystone)
    k3s+traefik+cert-manager+letsencrypt实现web服务全https
  • 原文地址:https://blog.csdn.net/kaimo313/article/details/125402805