《图解 Google V8》学习笔记Day91

CeShiYuan
• 阅读 146

消息队列:V8是怎么实现回调函数的?

从内部了解回调函数,可以帮助我们梳理清楚很多问题:
有助于我们理解浏览器中的Web API到底是怎么工作的;
有助于我们理解宏任务和微任务到底有哪些区别;
理解回调函数,是理解异步编程模型async/await的基础。

什么是回调函数?

其实回调函数也是个函数,它具有函数的所有特征,它可以有参数和返回值。回调函数区别于普通函数,在于它的调用方式。只有当某个函数被作为参数,传递给另外一个函数,或者传递给宿主环境,然后该函数在函数内部或者在宿主环境中被调用,我们才称为回调函数。
具体地讲,回调函数有两种不同的形式,同步回调和异步回调。通常,我们需要将回调函数传入给另外一个执行函数,那么同步回调和异步回调的最大区别在于同步回调函数是在执行函数内部被执行的,而异步回调函数是在执行函数外部被执行的
同步回调:举例 调用函数作为参数
异步回调:举例 setTimeoutUI

线程的宏观架构

UI线程:是指运行窗口的线程,当你运行一个窗口时,无论该页面是Windows上的窗口系统,还是Android或者iOS上的窗口系统。
在页面线程中,当一个事件被触发时,比如用户使用鼠标点击了页面,系统需要将该事件提交给UI线程来处理。
在大部分情况下,UI线程并不能立即响应和处理这些事件。
针对这种情况,我们为UI线程提供一个消息队列,并将这些待执行的事件添加到消息队列
中,然后UI线程会不断循环地从消息队列中取出事件、执行事件。
《图解 Google V8》学习笔记Day91
可以用一段JavaScript代码来模拟下这个过程:

function UIMainThread() {
    while (queue.waitForMessage()) {
        Task task = queue.getNext()
        processNextMessage(task)
    }
}

异步回调函数的调用时机

理解了UI线程的基础架构模型,下面我们就可以来解释下异步函数的执行时机了。
《图解 Google V8》学习笔记Day91
比如在页面主线程中正在执行A任务,在执行A任务的过程中调用setTimeout(foo, 3000),在执行setTimeout函数的过程中,宿主就会将foo函数封装成一个事件,并添加到消息队列中,然后setTimeout函数执行结束。
主线程会不间断地从消息队列中取出新的任务,执行新的任务,等到时机合适,便取出setTimeout设置的foo函数的回调的任务,然后就可以直接执行foo函数的调用了。
那么下面我们就来分析下XMLHttpRequest是怎么触发回调函数的?具体流程你可以参看下图:
《图解 Google V8》学习笔记Day91
结合上图,我们就可以来分析下通用的UI线程是如何处理下载事件的,大致可以分为以下几步:

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

总结

同步回调和异步回调,同步回调函数是在执行函数内部被执行的,而异步回调函数是在执行函数外部被执行的。
UI线程宏观架构
UI线程提供一个消息队列,并将待执行的事件添加到消息队列中,然后UI线程会不断循环地从消息队列中取出事件、执行事件。
关于异步回调,这里也有两种不同的类型,其典型代表是setTimeout和XMLHttpRequest。

此文章为5月Day23学习笔记,内容来源于极客时间《图解 Google V8》,日拱一卒,每天进步一点点💪💪
点赞
收藏
评论区
推荐文章
晴空闲云 晴空闲云
3年前
JavaScript中MutationObServer监听DOM元素详解
DOM的MutationObServer接口,可以在DOM被修改时异步执行回调函数,我的理解就是可以监听DOM修改。基本使用可以通过MutationObserver构造函数实例化,参数是一个回调函数。jsletobservernewMutationObserver(()console.log("change"));console.log(obs
菜园前端 菜园前端
2年前
什么是JavaScript异步模式
什么是异步模式?不会等待当前任务执行完毕,才会去执行下一个任务,这就是异步模式(Asynchronous)。开启异步后,就会跳过本任务,开始执行下一个任务,后续的逻辑一般会通过回调函数的方式定义。异步模式执行中,涉及到调用栈(Callstack)、消息队列
Chase620 Chase620
4年前
Promise从入门到拿Offer之手写Promise
1、Promise构造函数的实现Promise构造函数用来声明示例对象,需要传入一个执行器函数。其中包括resolve函数和reject函数,以及几个重要的属性:状态属性、结果属性和回调函数队列。构造函数的基本框架resolve函数用于异步处理成功后调用的函数。其中包括验证对象状态修改次数,修改promise实例对象状态,异步调用成功的回调函数
前端麦小子 前端麦小子
2年前
JavaScript异步的实现
你好,我是麦小子。编程领域的概念大多来自生活,异步也是如此。JS中的异步,有回调函数,期约,异步函数几种实现方式,一起探讨一下吧。
菜园前端 菜园前端
2年前
什么是回调函数?
原文链接:什么是回调函数?简单的来说,一个函数作为另外一个函数的参数,可以称为回调函数。这个理解其实不完全对,回调的意义根本没有体现出来,何为回调?也就是说一个函数你定义了,你没有马上的去调用它,而是交给了另外一个函数去调用,这才属于回调函数。缺点直接使用
Stella981 Stella981
3年前
CocosCreator编辑器脚本生命周期函数
CocosCreator为组件脚本提供了生命周期的回调函数。用户只要定义特定的回调函数,Creator就会在特定的时期自动执行相关脚本,用户不需要手工调用它们。目前提供给用户的生命周期回调函数主要有:onLoadstartupdatelateUpdateonDestroyonEnable
Stella981 Stella981
3年前
NodeJs中nextTick、setTimeout、setImmediate运行顺序解析
setImmediate该方法用来把一些需要长时间运行的操作放在一个回调函数里,在浏览器完成后面的其他语句后,就立刻执行这个回调函数。setImmediate是宏任务,优先级是比定时任务低的。除非在定时任务中。测试代码:setImmediate(function(){console.log("setImmediate");
Stella981 Stella981
3年前
AVIOInterruptCB结构体分析
1AVIOInterruptCB结构体定义在/usr/include/libavformat/avio.h中有如下的结构体定义,根据头文件中的注释:这是一个回调函数和参数的结构体。有些函数是在阻塞的,用这个回调函数来检查是否中断这个阻塞函数,如果回调函数返回1,那么这个正在阻塞的操作将被中止。那么就用这个结构体里的参数opaque来回调其中的callb
Stella981 Stella981
3年前
JavaScript回调函数的高手指南
摘要:本文将会解释回调函数的概念,同时帮你区分两种回调:同步和异步。回调函数是每个前端程序员都应该知道的概念之一。回调可用于数组、计时器函数、promise、事件处理中。本文将会解释回调函数的概念,同时帮你区分两种回调:同步和异步。1.回调函数首先写一个向人打招呼的函数。只需要创建一个接受name参数的函数gree
Stella981 Stella981
3年前
ES6 Promise 对象扯谈
newPromise(/executor/function(resolve,reject){...});Promise的构造函数接收一个函数作为参数,函数里面传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。其实这里用“成功”和“失败”来描述并不准确,按照标准来
Stella981 Stella981
3年前
ES6 Promise
Promisepromise是异步编程的一种解决方案1什么是异步?异步模式,每一个任务有一个或多个回调函数(callback),前一个任务结束后,不是执行后一个任务,而是执行回调函数,后一个任务则是不等前一个任务结束就执行,所以程序的执行顺序与任务的排列顺序是不一致的、异步的。"异步模式"非常重要。在浏