UI多线程-你需要知道的JS执行机制原理

本文深入探讨了JavaScript的执行机制,包括单线程、同步任务、异步任务及其处理方式。浏览器常驻线程如JS引擎线程、GUI线程、HTTP请求线程和定时触发器线程协同工作,通过事件循环(Event Loop)实现异步执行。理解这一机制有助于提升开发效率和解决调错问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

为什么要了解JS执行机制?
JS执行机制是js执行的底层原理,理解了底层原理对于开发方法效率会提高,调错都效率也会增加很多。在未来发展道路上,了解底层才能够在技术的道路上走得更远!下面来和总结一下js执行机制原理吧。我从浏览器常驻的线程逐一说起。

浏览器常驻的线程

  1. js引擎线程(js主线程)
    js执行是单线程,也就是说同一时间内只能做一件事(同步),但是js中也包含一些异步的事情,比如我们下班介绍的一些。
  2. GUI线程(绘制用户界面与JS主线程是互斥)
    这个线程大家听起来可能比较陌生,但是这是大家一直在开发中看到的东西。大家回忆一些button按钮,我们点击时按钮颜色的变化,这个线程就是由GUI线程决定的!
  3. http网络请求线程(处理用户GET POST请求,等返回结果后将回调函数推入到任务队列当中)
    比如ajax的请求就是异步,和js主线程也是互斥的!
  4. 定时触发器线程(setTimeout,setInterval等待时间结束后把执行函数推入任务队列当中)
  5. 浏览器事件处理线程(将 click、mouse 等交互事件发生后将这些事件放入事件队列中)
    以上的GUI线程,http网络请求和定时器,浏览器事件处理线程均是异步的和js主线程是互斥的。

JS执行机制

js是单线程,意思是js在执行代码的时候那么其他的任务就不能做。但是当有异步的任务时发生的步骤也是非常重要的。

JavaScript 是基于单线程运行的,同时又是可以异步执行的,一般来说这种既是单线程又是异步的语言都是基于事件来驱动的,恰好浏览器就给 JavaScript 提供了这么一个环境

js执行的的顺序

  1. 判断是同步任务还是异步任务
  2. 同步的话放入js主线程执行栈中,异步的先放入事件注册当中(Event Table)
  3. 比如异步的时间是ajax请求,让请求成功的时候,异步的函数并不会执行执行而是放入到任务队列(Event queue)当中的第一位。如果还有异步任务比如定时器,当定时器的时间到的话,放入到任务队列当中的第二位。
  4. 当js主线程执行完任务,执行栈为空的时候,会去任务队列(Event queue)中看是否有其他任务,按顺序(先进先出)依次放到执行栈中执行,先执行ajax,然后执行完主线程为空,再去Event queue中拿定时器执行。执行完在去看任务队列中是否有,形成事件循环(Event loop)。

同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入 Event Table 并注册函数。

当指定的事情完成时,Event Table 会将这个函数移入 Event Queue 。

主线程的执行任务完毕为空,会去 Event Queue 读取对应的函数,进入主线程执行。上述过程会不断重复,也就是常说的 Event Loop (事件循环)。

下面来一张流程图,这样看起来更加的清晰!
在这里插入图片描述
在这里需要注意的是一开始一定的先执行js主线程中的东西,执行完之后才去任务队列中拿任务到js主线程中继续执行。如果js主线程是一个死循环呢?那么他后面的异步任务还会执行吗?当然不会,js主线程执行不完,其他异步任务不可能触发执行,一直在任务队列中等待js主线程运输执行。

<script> 
	while(true){
		console.log("Ahua");
	}
	setTimeout(function () {
	console.log(123);
},100)
//永远都不会打印123   同时这也是造成定时器不准的一个原因 本来100ms就应该执行定时器,现在却永远不会执行。因为js主线程始终执行不完
</script>

JS引擎线程和GUI线程互斥
JS可以操作DOM元素,进而影响到GUI的渲染结果,因此JS引擎线程与GUI线程是互斥的。也就是说当JS主线程处于运行状态时,GUI渲染线程将处于冻结状态。

JS执行机制多线程不好吗
js主要做的工作是用户交互体验,处理DOM,如果js是多线程的,那么想这么一个场景。在同一时间,一个线程想要修改DOM,另外一个元素想要删除这个DOM,浏览器不知道听谁的,如果引入锁的机制,那么就和其他语言一样尴尬了! 所以JS主线程还是非常棒的!

单线程计算能力有限,如果有大量数据操作怎么办?
如果有大量数据操作的话,那么就需要配合后端操作了,VUE月nodejs配合也就是SSR技术。

同步任务

同步任务

执行栈------相当于 js 主线程

function foo(ot){
    function bar(it){
        console.log(it); // 先输出20
    }
    bar(20);
    console.log(ot); // 后输出10
}
foo(10);
  1. 代码没有执行的时候,执行栈为空栈

  2. foo 函数执行时,创建了一帧,帧中包含了形参、局部变量 (预编译过程) ,把帧压入栈中

  3. 执行 foo 函数内代码,执行 bar 函数

  4. 创建新帧,同样有形参、局部变量,压入栈中

  5. bar 函数执行完毕,弹出栈

  6. foo 函数执行完毕,弹出栈

  7. 执行栈为空

异步任务

$.ajax({
    url:'localhost:/js/domo.json',
    data:{},
    success:function(data){
        console.log(data);
    }
});
console.log('run');
  1. Ajax 进入 Event Table,注册回调函数 success,执行 console.log( ‘run’ )

  2. Ajax 事件完成 http 网络请求线程把任务放入 Event Queue 中

  3. 主线程( 调用栈 )读取任务执行 success 函数

关于定时器 setTimeout,setInterval

js 引擎底层是红黑树,当程序执行时,定时器会将其推送到任务队列中,只有当 js 的同步任务全部执行完毕之后,才会进行时间间隔,执行定时器,基于以上两点,定时器是不准确的

setTimeout的等待时间结束后并不是直接执行的而是先推入浏览器 的一个任务队列,在同步队列结束后在依次调用任务队列中的任务。

setTimeout(function(){}, 0)Js主线程中的执行栈为空时,0毫秒实际上也达不到的,根据HTML标准,最低4毫秒。

setInterval是每隔一段时间把任务放到Event Queue之中

function test (num) {
	for (var i = 0; I < num; i++) {
		console.log(i);
	}
}
 
setTimeout(function () {console.log(‘time’)}, 400);
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值