JavaScript的执行机制(同步任务、异步任务、微任务、宏任务)-凤巢SEO
轻识Logo
前端历劫之路

共 4393字,需浏览 9分钟

 ·

2022-01-16 15:15

概念理解

关于JS

JS是一门单线程语言,在最新的HTML5中提出了Web-Worker,但JS是单线程这一核心仍未改变。所以一切JS版的"多线程"都是用单线程模拟出来的。

多线程/单线程的简单理解

  • 多线程: 程序可以同一时间做几件事。

  • 单线程: 程序同一时间只能做一件事。

JS为什么是单线程的?

JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊。

JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准?

所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。

为了利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。所以,这个新标准并没有改变JavaScript单线程的本质。

JS为什么需要异步?

如果JS中不存在异步,只能自上而下执行,如果上一行解析时间很长,那么下面的代码就会被阻塞。对于用户而言,阻塞就意味着"卡死",这样就导致了很差的用户体验。

JS单线程又是如何实现异步的呢?

既然JS是单线程的,只能在一条线程上执行,又是如何实现的异步呢?是通过的事件循环(event loop),理解了event loop机制,就理解了JS的执行机制。理解事件循环机制前,我们先来看看任务队列。

任务队列

"任务队列"是一个事件的队列(也可以理解成消息的队列),IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈"了。主线程读取"任务队列",就是读取里面有哪些事件。"任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。

所谓"回调函数"(callback),就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。

"任务队列"是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上是自动的,只要执行栈一清空,"任务队列"上第一位的事件就自动进入主线程。

但是,由于存在后文提到的"定时器"功能,主线程首先要检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。读取到一个异步任务,首先是将异步任务放进事件表格(Event table)中,当放进事件表格中的异步任务完成某种事情或者说达成某些条件(如setTimeout事件到了,鼠标点击了,数据文件获取到了)之后,才将这些异步任务推入事件队列(Event Queue)中,这时候的异步任务才是执行栈中空闲的时候才能读取到的异步任务。

JS的执行机制-->事件循环(Event Loop)

主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。Event Loop是JS的执行机制。

setTimeout(fn,0)

setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,尽可能早得执行。它在"任务队列"的尾部添加一个事件,因此要等到同步任务和"任务队列"现有的事件都处理完,才会得到执行。

HTML5标准规定了setTimeout()的第二个参数的最小值(最短间隔),不得低于4毫秒,如果低于这个值,就会自动增加。在此之前,老版本的浏览器都将最短间隔设为10毫秒。

另外,对于那些DOM的变动(尤其是涉及页面重新渲染的部分),通常不会立即执行,而是每16毫秒执行一次。这时使用requestAnimationFrame()的效果要好于setTimeout()。需要注意的是,setTimeout()只是将事件插入了"任务队列",必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数。要是当前代码耗时很长,有可能要等很久,所以并没有办法保证,回调函数一定会在setTimeout()指定的时间执行。

JS的同步和异步

单线程的不足

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务, 简单理解就是排好队一个一个来。如果前一个任务耗时很长,后一个任务就不得不一直等着。如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。

同步和异步解决单线程的不足

JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。

于是,所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。



通过一个小例子来理解:

下课后甲、乙、丙、小明、丁5个人一起到食堂排队打饭,排好队一个一个来。小明发现就他忘记带饭卡了,为了不影响后边的同学打饭,于是小明离开了队伍,在一旁等同学把他的饭卡带来,他再打饭。这里的排队相当于js的执行栈,排队打饭这件事就是同步。小明等同学送饭卡来这件事就是异步。通过饭卡划分了同步和异步。小明只有满足了有饭卡这个条件,通知阿姨他有饭卡了。食堂阿姨优先给甲乙丙丁打饭,最后再给小明打饭。

其实同步和异步,无论如何,做事情的时候都是只有一条流水线(单线程 [js就是单线程的,不会变]),同步和异步的差别就在于这条流水线上各个流程的执行顺序不同,先执行同步任务,最后再来执行异步任务。

异步任务又分为宏任务和微任务

宏任务(macro task)

  • 定时器;
  • 事件绑定;
  • ajax;
  • 回调函数;
  • Node中fs可以进行异步的I/O操作;

微任务(micro task)

  • Promise(async/await)  => Promise并不是完全的同步,在promise中是同步任务,执行resolve或者reject回调的时候,此时是异步操作,会先将then/catch等放到微任务队列。当主栈完成后,才会再去调用resolve/reject方法执行;

  • Process.nextTick (node中实现的api,把当前任务放到主栈最后执行,当主栈执行完,先执行nextTick,再到等待队列中找);

  • MutationObserver   (创建并返回一个新的 MutationObserver 它会在指定的DOM发生变化时被调用);

执行顺序优先级:SYNC => MICRO => MACRO。

所有JS中的异步编程仅仅是根据某些机制来管控任务的执行顺序,不存在同时执行两个任务这一说法。




console.log("同步任务1");

function asyn(mac{
    console.log("同步任务2");
    if (mac) {
        console.log(mac);

    }
    return new Promise((resolve, reject) => {
        console.log("Promise中的同步任务");
        resolve("Promise中回调的异步微任务")
    })
}
setTimeout(() => {
    console.log("异步任务中的宏任务");
    setTimeout(() => {
        console.log("定时器中的定时器(宏任务)");

    }, 0)
    asyn("定时器传递任务").then(res => {
        console.log('定时器中的:', res);
    })
}, 0)
asyn().then(res => {
    console.log(res);
})
console.log("同步任务3")

输出结果依次为:

// 同步任务1
// 同步任务2
// Promise中的同步任务
// 同步任务3
// Promise中回调的异步微任务
// 异步任务中的宏任务
// 同步任务2
// 定时器传递任务
// Promise中的同步任务
// 定时器中的: Promise中回调的异步微任务
// 定时器中的定时器(宏任务)

先输出“同步任务1”,往下遇到setTimeout异步宏任务,先放到宏任务队列中挂起,往下遇到同步任务asyn(),执行asyn函数,输出函数中的“同步任务2”,返回Promise,输出“Promise中的同步任务”,遇到resolve()回调函数,.then函数块属于异步微任务,先放到微任务队列中挂起,往下执行,输出“同步任务3”,至此,同步任务执行结束,执行栈为空。

先执行微任务队列.then函数块,输出“Promise中回调的异步微任务”,此时微任务队列为空。

然后看下定时器模块时间是否到了,到了就执行宏任务队列,先输出“异步任务中的宏任务”,遇到里层定时器,先放到宏任务队列,往下执行,调用函数asyn,执行里面的同步任务,输出“同步任务2”,在输出“定时器传递的任务”,返回Promise,执行promise中的同步代码,输出“Promise中的同步任务”,遇到.then,先放到微任务队列。此时,执行栈又为空。

先执行微任务队列,输出 “定时器中的:Promise中回调的异步微任务”,此时微任务队列为空。执行宏任务,输出“定时器中的定时器(宏任务)”。程序执行完毕。




关于本文:

作者:zwnsyw

https://www.cnblogs.com/zwnsyw/p/12772668.html

声明:文章著作权归作者所有,如有侵权,请联系小编删除。


浏览 48
点赞
评论
收藏
分享

手机扫一扫分享

图片
表情
点赞
评论
收藏
分享

手机扫一扫分享

相关内容推荐

哈尔滨企业建站平台188建站官网沈阳自建站模板雷州网站建站推广唐山建站模板网站廊坊模板建站软件易建站手游北京博客建站模板唐山模板建站培训行唐 盘古建站南宁模板建站工具郑州品牌自助建站c 网页建站教学小企业建站空间杭州自助建站公司cms建站系统 推荐微牛牛建站中心威海荣成企业建站婚纱外贸自建站八亿wap建站系统建站 嘉立创企业建站源码价格凡科建站之家自主域名免费建站翼启云建站建站油气有范围建站准备哪些东西安徽网络建站推销cms建站系统大全织梦建站样式免费php建站空间企业建站公司方案阿里云教育建站邢台自助建站服务网站建站后期维护武汉建站模板源码php通用建站程序建站教程视频大全海口模板设计建站怎样自助建站空间网络建站活动简介邯郸做建站地方宝塔稳定吗建站广元模板自助建站360免费建站av快速建站框架选择徕卡仪器自动建站vue小程序建站触网建站全功能自助建站个人模板建站运营方案长乐古槐镇建站凡特在线建站泉州模板建站软件科讯建站视频wp建站和pageadmin如何用aspcms建站微指客建站合资建站的口号云建站宣传视频微商建站图片河北建站公司效果shoptop专业建站师vip影院建站系统广州自助建站公司建站公司推荐discuz白湖亭福建站牌清远网站建设建站免费 云建站app建站主机ip怎样开展建站业务建站怎么安装erp常德网站建站方案湛江建站网道外小程序建站python建站环境搭建建站推广哪家强一建建站系统企业自我建站模板惠州模板建站流程天津跳板搭建站网站搭建优化建站建站程序的特点学校 骏域建站建站哪个公司最好灵武自适应建站榆社自助建站系统洛阳建站哪家强太原外贸建站推广后方交会建站以后性用品自建站广西外贸建站推广移动建站落地页佛山建站模板外贸陆埠自助建站外包公司建站佛山免费自助建站建站仿站图解东莞独立网站建站潜山自助建站推荐昆明云翼建站义马企业自助建站美橙定制建站用户建站的目的中国铁塔建站补偿廊坊模板建站优点新媒体建站企业win2012 建站苏州杭州建站优化cms政府建站系统自助建站怎么升级玖勤科技建站cms在线建站系统长沙建站公司哪有凡科建站ceolinux建站访问项目主机宝怎么建站夸克建站官网易坤云建站天津英文建站模板建站入门者专属淮安外贸建站k3建站检车站建站申请如何使用自主建站自助建站免费用视频网页建站温州响应式建站江门智能建站模版pc网站建站合同各类企业建站流程旅游盘古建站安丘企业建站价格龙口建站怎么选小白建站教程视频网站建站怎么选如何选择域名建站运城自建站推广利用七牛建站承德外贸建站推广嘉兴建站公漳州自助建站seo南宁如何模板建站title商丘企业建站悦然外贸建站夸克建站系统源码池州响应式建站联创云建站常州企业模板建站德阳模板建站厂家建站模板有几种凡科建站技巧梁平专业建站公司建站 站内搜索二次建站南平营销建站公司礼县妇幼保建站韬达建站技术gps移动站建站护卫神本地建站自建站商城转让江门建站系统推荐烟台培训公司建站河源建站哪家好张华兴建站易建站推广方案网上答题建站模板自助建站实现方案模仿建站价格真实免费建站平台即下载橙子建站云南网站建站建设简单建站模板下载只会模版建站的人中国建站流程好用的建站公司自助建站设计代理随州专业的建站金之麦建站decms建站安全吗涟源专业建站公司wazap自建站引流托拽自助建站云南景洪云建站北京快速建站技术陕西网络建站公司共建站大数据手机端建站系统双色球福建站嘉善建站推广价格扬州建站推广报价建站之星安全吗建站模式哪种好shopify如何自建站小程序建站排名南宁企业免费建站柘城网站建站公司php和java建站浙江嵊州福建站附海自助建站

合作伙伴

凤巢SEO

www.imeiying.com
kuai.urkeji.com
seo.xtcwl.com
www.maijichuang.cn
www.jsfengchao.com
top1.urkeji.com
www.hz.bj.cn
www.lyhbj.cn
jl.urkeji.com
niu.seo5951.com
www.weiwin.cc
zz1.urkeji.com
www.conductive-powder.com
www.chaoshanxing.com
seo.chaoshanxing.com
www.snlanyards.com
www.maijichuang.cn
www.imeiying.com
idc.urkeji.com
seo.xtcwl.com