这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战
前言
知识梳理---JS异步编程传送门
- 异步机制(进程线程、chrome浏览器架构、EventLoop机制)
理解JS异步编程
案例分析
同步代码
// 通过阻塞主进程 实现延时两秒后执行某操作
const test = () => {
let t = +new Date();
while (true) {
if (+new Date() - t >= 2000) {
break;
}
}
};
console.log(1);
test();
console.log(2);
console.log(3);
异步代码
// 通过setTimeout实现延时两秒后执行某操作
console.log(1);
setTimeout(() => {
console.log(2);
}, 2000);
console.log(3);
同步的特点:调用之后得到结果,再干别的任务
异步的特点:调用之后不管结果,继续干别的任务
这样的解释是初级的,是最具有直观感受的一种解释。当引入线程这个概念之后,能解释得更清晰,但同时也就没有那么直观,对初学者不友好。
结论
同步:JavaScript主线程调用函数之后,主线程继续执行函数调用,等到了函数调用结束,主线程再执行后续的任务。
异步:JavaScript主线程调用函数之后,由其他线程(非JavaScript主线程)执行函数调用操作,主线程继续执行后续任务。(其他线程执行完,通过浏览器的异步机制,把回调函数放在任务队列中,待主线程执行。这个过程比较复杂,有很多值得研究的细节,这里只是给一个笼统的说辞,会在本文的EventLoop机制中进行分析。)
ps:这里不对线程做过多的展开,把它理解为一个独立的处理单元就好了。这里需要有一个清醒的认知,JavaScirpt是一门单线程语言(其实就是执行线程是单线程的,跟语言没啥关系)。单线程JavaScript实现异步的核心是借用浏览器内核多线程实现的异步。大体上,异步的本质是线程间的通信,浏览器JavaScirpt线程与其他线程之间的通信机制就是EventLoop机制。
这里的内容不做深入讨论,简单的堆砌一下自己零散的理解,没有技术,全是感情。
主要目的理解同步与异步的区别,就在于同步就是JavaScript主线程自己一个人玩,异步就是JavaScript主线程 与 浏览器当前进程下其他线程玩,浏览器制定了一套玩法 EventLoop机制)
至此,异步机制的所有核心概念也就全部登场了:同步、异步、浏览器、进程、线程、EventLoop机制。这些概念好比一堆珍珠,接下来先打磨一下珠子,然后找一根线把这些珍珠穿起来。
chrome浏览器多进程架构
工厂-CPU
车间-进程(CPU所能处理的单个任务,能拥有资源和独立运行的最小单位)
工人-线程(线程是程序执行的最小单位)
多进程与多线程
- 多进程:多进程指的是在同一个时间里,同一个计算机系统中如果允许两个或两个以上的进程处于运行状态。多进程带来的好处是明显的,比如你可以听歌的同时,打开编辑器敲代码,编辑器和听歌软件的进程之间丝毫不会相互干扰。
- 多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
这里是对浏览器多进程架构的一个简单介绍。重点不在于深入理解浏览器,而在于把应用程序、进程、线程这三个抽象的概念通过浏览器聚在一起。把我们脑海里的传统的JS运行在浏览器中的简单黑盒模型,转换成程序、进程、线程的复杂模型。复杂的意义在于为后期理解更为复杂协程,任务队列,NodejsEventLoop机制,打好基础做铺垫。如果没有这一步铺垫,之后的路大概率会白给。(这里的目的是为了理解异步,不要把注意力散去研究浏览器了)
了解浏览器的多进程架构,理解进程,线程这些概念。当自己没有明确的目标的时候,不要去研究,因为,真学不完。
异步场景-定时器
定时器的应用实例 : 防抖、节流、倒计时、动画
简单定时器代码
// 通过setTimeout实现延时两秒后执行某操作
console.log(1);
setTimeout(() => {
console.log(2);
}, 2000);
console.log(3);
大体执行流程
- 主线程调用WebAPI,setTimeout
- 定时器线程 计数两秒(JS线程不负责计时)
- 事件触发线程将定时器事件放入任务队列
- 主线程通过EventLoop遍历任务队列
EventLoop机制
浏览器端的EventLoop机制
图片参考链接
task(宏任务)、microtask 微任务、queue(任务队列)、call stack(执行栈)
OK,这些珠子都好像被聚在一起了,我们再用历史的线把他们串在一起。
梳理思路:参考极客时间 浏览器工作原理与实践 李兵
第一版:单线程模型
第二版:引入事件循环机制(事件 和 循环机制 这是两个概念)
循环:让主线程一直在执行
事件:在有任务时启动,空闲时挂起
事件循环机制让线程活了起来
第三版:多线程模型
第四版:宏任务,微任务
ps:其实只有微任务microtask这个概念,宏任务就是task。每一个task都会有一个microtask queue(微任务队列)
如果大家博客文章看得多,很容易忽视一个问题。什么是微任务,为什么要有微任务。很容易进入一个误区,Promise面试题那么多,Promise产生的是微任务,那微任务就一定有,一定存在,存在就是合理。这样的思维方式是不值得倡导的。
微任务队列,微任务的提出,都是因为针对task的弊端所做的一种平衡。
这个task的弊端就是,task的回调进入了任务队列,这里的任务队列没有优先级。意味着先执行的task的回调,可能很晚才被放到任务队列中执行。
具体到一个场景,监听DOM节点的变化,如果是同步执行,则会阻塞其他任务,如果异步执行添加任务队列尾部,又无法满足实时性。所以这里采用了微任务做平衡,每一个task都会有一个微任务队列,执行完task后,会立即检查当前task中的 microtask queue,执行相关的回调。即microtask queue 只是task的一个部分而已。不要被宏任务,微任务这样的词给迷惑了,他们不是独立的,反而是包含关系。
参考:
imweb.io/topic/58e3b…
html.spec.whatwg.org/multipage/t…
time.geekbang.org/column/arti…
html.spec.whatwg.org/multipage/w…
PS:临表涕零,不知所言。模型,流程图还是得习题检验。经得住习题检验的思维模型,才能hold住全场。把promise,async/await梳理完再来一次思维梳理。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!