JS执行机制详解,定时器时间间隔的真正含义听风是风

学或不学,知识都在那里,只增不减。

#壹引

通过结果倒推过程是我们常用的思考模式,我在上一篇学习promise笔记中,有少量关于promise执行顺序的例子,通过倒推,我成功让自己对于js执行机制的理解一塌糊涂,js事件机制,事件循环是面试常考的点,弄懂它们是贼有必要的。

回顾下我学习promise的心理历程:

letp=Promise.resolve(1);p.then(resp=>console.log(resp));console.log(2);//2//1哦,原来如此,同步代码会先执行,先输出2,所以then回调是异步。

letp1=Promise.resolve(1);p1.then(resp=>console.log(resp));letp2=Promise.resolve(2);p2.then(resp=>console.log(resp));//1//2哦!多个异步,先注册的回调先执行,原来如此。

setTimeout(()=>console.log(2),0);letp1=Promise.resolve(1);p1.then(resp=>console.log(resp));//1//2嗯????不是先注册的异步先执行?为啥这里先输出1,promise学习下来,成功让自己懵逼。

理解JS执行机制是很重要的,它会让你的代码调试更符合自己的预期,其次对于面试也非常有帮助。

贰JavaScript中的同步异步

你会想,为什么要同步?

JavaScript本身是一门浏览器脚本语言,更多负责用户的交互,dom操作之类;假设JS并非单线程,我让两个行为同时操作一个dom对象,那岂不是乱套了。想想我们排队取餐吃饭,如果不排队,往往容易引发争吵,编程也是现实行为的抽象。

也许你会说,不是有webworker吗,但webworker属于浏览器的解决方法,并非JavaScript;浏览器虽然可以开多个线程,但每个线程仍然是单线程,而且也不被允许操作dom,这依旧没改变JS是单线程语言的事实。

可在开发中我们得处理大量的网络请求,我们知道请求可能存在延迟,服务器查询也得耗时,一次请求受诸多不确定因素影响,我们不可能让一次网络请求堵塞后面的程序。

也正因如此异步诞生了,对于不确定的网络请求,定时器之类,咱先备注一下有这些需要处理,就接着去忙同步的事情了,等手头上同步的处理完了,再来解决先前备注的异步事件。

想想我们排队取餐吃饭,前面的哥们大声说道,牛肉面不要面只要牛肉,多葱多蒜少辣不吃香菜半小时后来取,老板也不会等他半小时把面取了再做后面顾客的生意,那真要这样,店子早倒闭了。

那么说完同步异步,我们大概有了个抽象的概念,js会先执行同步,万一遇到异步,就先备注下有这个异步,等同步跑完了咱再来处理异步的后续操作,那么站在js角度这个过程是什么样的,我们接着说。

叁执行栈与任务队列

我们都知道,当一个方法被调用时,JavaScript会生成一个属于此方法的执行环境,也叫执行上下文,这个上下文中存放着方法依赖的参数,变量以及作用域等等。

什么是执行栈呢?当调用一个方法A时,这个方法可能也会调用另一个方法B,B还可能调用方法C,而JS只能同时一件事,所以方法B、C没执行完之前,方法A也不能被释放,那总得找个地方把这些方法按顺序存一存吧,存放的地方就是执行栈。

执行栈是存放同步方法调用的地方,遵从先进后出的规则:

letA=()=>{B()console.log(1);};letB=()=>{C()console.log(2);};letC=()=>{console.log(3);};A();//321上述代码站在执行机制角度来看,是这样的,你应该也能理解递归处理不好陷入死循环后爆栈是个什么情况了:

凭直觉来想,异步任务不可能直接在执行栈中执行,不然绝对存在堵塞的问题,那先存放在哪呢?放在了任务队列中。

那么到这里我们又有了一个模糊的概念,同步任务与异步任务存放的地方不同,有个问题,JavaScript怎么知道什么时候去执行异步任务呢?那就不得不说事件循环。

肆事件循环(EventLoop)

当一个任务被执行,js会判断是否为同步任务,如果是同步,压入主线程立即执行;但如果是异步任务,移到异步处理模块(TaskTable),当异步任务有了结果,就将异步任务的回调函数注入到任务队列中等待。

当主线程的同步任务执行完毕执行栈为空,js引擎就会读取任务队列中的第一个任务加入到执行栈执行,当此任务完成,继续重复此类操作,这也就是事件循环了,任务队列满足先进先出的特性。

伍宏任务与微任务

我们先对宏任务微任务做个大概分类:

macro-task(宏任务):script环境setTimeout、setInterval、I/O、事件、postMessage、MessageChannel、setImmediate(Node.js)

micro-task(微任务):Promise的thencatchfinally,process.nextTick,MutaionObserver

很多面孔没见过,没关系,好歹我们知道了定时器是宏任务,thencatchfinally是微任务。我把上面的例子搬下来:

setTimeout(()=>console.log('我第一'),1000);letp1=Promise.resolve('我第二');p1.then(resp=>console.log(resp));//我第二//我第一明明是定时器先进的异步处理模块,结果promise.then还要早于定时器先执行,为什么呢?

这是因为,异步任务中又分为宏任务与微任务两种,当执行栈为空,JS引擎会优先处理微任务队列的任务,等到微任务队列处理完成,才会处理宏任务队列的任务。

setTimeout(()=>console.log('我第一'),2000);letp1=Promise.resolve('我第二');p1.then(resp=>console.log(resp));setTimeout(()=>console.log('我第三'),1000);letp2=Promise.resolve('我第四');p2.then(resp=>console.log(resp));//我第二//我第四//我第三//我第一上述代码中,不管你异步代码是怎么个顺序,我们可以明确的是微任务优先级总是高于宏任务。

但需要注意的是,script整体环境都是一个宏任务,所以微任务由宏任务执行过程中产生,除去同步代码执行完毕后,微任务执行优先级总是要优于剩余的异步宏任务。这里引用一张图:

上图中,宏任务运行过程中可能会产生微任务,若有微任务,执行所有微任务(前期是同步代码跑完了),微任务优先级始终高于宏任务(抛开同步代码)。

陆有趣的定时器

定期器分为一次性定时器setTimeout与周期性定时器setInterval,前者是等待N秒之后执行回调一次没了,后者是每隔N秒执行回调一次。

有这么一个定时器:

setTimeout(()=>console.log('我第一'),3000);setTimeout(()=>console.log('我第二'),3000);你猜这两个定时器怎么执行?先等三秒打印“我第一”,再等三秒打印“我第二”吗?其实不是,真正执行是是等待三秒后几乎无间隔的同时打印2个结果。

我们可以脑补下执行顺序,首先遇到第一个定时器,告诉异步处理模块,等待三秒后将回调加入任务队列,然后又调用了第二个定时器,同样是3秒后将回调加入任务队列。

等到执行栈为空,去任务队列拿任务,执行第一个console,这要不了多久,于是几乎无时差的又去任务队列拿第二个任务,这也导致了为什么2次输出几乎在同时进行。

那么本文到这里就结束了。

一个一次性定时器是这样:

setTimeout(callback,time);很多人会将上述代码理解为,等待time秒后就会立刻执行callback。但事实上time真正的含义是等待time秒后,将callback加入异步任务队列。当主线程同步代码都跑完执行栈此时为空,此时事件机制会跑去异步任务队列中看看有没有异步任务可以执行,一看有个callback,那就取出这个callback,然后去执行它。

setTimeout(()=>console.log(1),2000);setTimeout(()=>console.log(2),1000);上述代码中存在两个定时器S1与S2,S2在等待1秒后将callback加入了任务队列,之后又过了一秒将S1的callback加入任务队列,所以表现为等待1秒输出1,之后又等待1秒速出2,两者间隔为1S。

所以关于定时器唯一需要强调的是,callback加入任务队列不表示会立即执行,同步代码,promise这些没走,它就得等着,比如:

newPromise就像newArray一样,它是一个同步执行过程,异步的是then,then执行的前置条件是promise的状态改变了(不再是pending),所以上述例子改变状态的正是resolve()这一句。

我们来模拟这个过程:

constP1=()=>(newPromise((resolve)=>{console.log('p1');resolve()}));constP2=()=>(newPromise((resolve)=>{console.log('p2');resolve()}));setTimeout(()=>{console.log('s1')P1().then(()=>{console.log(1);})})setTimeout(()=>{console.log('s2')P2().then(()=>{console.log(2);})})总结来说,就是在2个定时器中分别调用了2个promise,唯一需要考虑就是是先输出1还是先输出s2。因为全局就存在2个定时器,所以肯定先执行定时器S1,先输出s1之后调用了P1,自然紧接着输出p1,p1改变状态同步(resolve),因此接着跑then输出了1了,同等条件下微任务优先级比宏任务高,所以答案为s1p11s2p22。假设P1的resolve被一个定时器包裹,你会发现就是先输出s2,最后输出1了。

在上文中,我贴出了一个定时器与promise执行对比的例子,提到promise状态变了,就会立刻执行then,这句话就给人一种状态变化了then就会立马执行的错觉,这句话有歧义,我们来看个例子:

我们将外层Promise简称P1,内部Promise简称P2,P1的resolve是同步改变的,按照上文的说法,那不应该立马执行P1的then回调吗,如果是这样结果应该是4312才对,状态先变先执行,这句话没错,但不够完善,我们来解释这个问题。

首先我们要清楚,Promise异步的是什么,异步的是then吗?其实并不是,真正异步的是then里面的callback,比如上述代码中这一句:

newPromise(resolve=>{resolve(2)}).then((t)=>console.log(t));异步的是(t)=>console.log(t),而newPromise().then()这一句是同步执行的,它做了什么?它创建了一个Promise实例,然后调用了实例上的then方法,告诉Promise,我这里有个callback,你先帮我记录好,等同步跑完了,我的状态也改变了,你再帮我执行它。

所以对于P1这个外层Promise而言,它里面的三句代码(抛开P2的callback)都是同步执行的,因此P2的callback是先加入异步队列的,此时P1的then都还没执行,自然P1的callback都没加入队列,怎么能先输出1呢?因此执行过程其实是这样:

遇到P2的then,把P2的callback加入异步队列--->输出4--->把P1的callback加入任务队列--->输出3--->两个promise改变状态都是同步的,肯定是先加入的先执行(P1确实先改状态,但是P1callback那时候都没加入队列,没的执行),最终输出4321。

我们把问题升级,改成更符合我们日常网络请求的情况,来看代码:

要这样想,虽然P2的callback先加入队列,假设这个请求要10S才响应,而P1callback虽然加入的晚,但是1S就拿到请求改状态了,P1怎么可能等待P210S让它先执行后自己才执行呢,这不符合我们日常开发逻辑。

总结来说,Promise状态变了callback确实应该立刻执行,但前提是同步代码走完了,且你的callback有先注册进去,.then不是异步,异步的是里面的callback,.then也是在告诉Promise我有个callback需要你存起来,等时机到了,你再帮我执行,这个过程是个异步行为,补充完毕。

THE END
1.8023是何含义8023 可用手势表示8 就是把左手大拇指和食指岔开竖放代表 L0 是一个圆圈代表 O2 岔开食指和中指代表 V3 岔开中指、无名指、小拇指横放代表 E合起来就是 LOVE。 8023 也有谐音含义8 谐音把0 谐音你2 谐音爱3 谐音上合起来是把你爱上。 它最初用于不能发声或与听力障碍者交流的场合现在被年轻人在网络上大量https://m.pcauto.com.cn/baike/831410/1628965/
2.遇事只会哭的废物来自叫什么叫8023叫什么叫8023 24-12-4 22:28 发布于 湖南 来自 iPhone客户端 遇事只会哭的废物 L叫什么叫8023的微博视频 小窗口 ?收藏 转发 评论 ?赞 评论 o p 同时转发到我的微博 按热度 按时间 正在加载,请稍候ü 简介: 大步向前走,不要回头看 更多a 微关系 她的关注(https://weibo.com/5428489128/5107987130094230
3.8023和5178206网络用语的真正含义你知道吗?阿灿告诉大家,随着科技的进步和网络的发展,新的网络用语层出不穷。 我们首先来说说8023,这个数字手势网络流行语的真正含义是LOVE,也就是“我爱你”的意思。可是,阿灿发现,在抖音上一些女性把8023说成了未婚、不要彩礼、接受婚检等等意思,其实完全是为了追求点击量而已。不过,无论怎样解读,8023都是表达爱意的方式https://acan360.com/71780.html
4.8023数字究竟代表什么意思?8023的真正含义8023的真正含义 前几天看到一个视频,说的是一个女孩误将8023发给了一个男同事,这个男同事不知啥意思,就问女孩,你给我发8023是啥意思?弄得女孩尴尬极了。 那么这个8023数字究竟代表什么意思呢?这么受年轻人青睐。 其实,8023这个梗来自于爱情物语书,是一个经典的数字手语,是最近网络上十分流行的网络用语,它的https://www.bzx1688.com/g/523988.html
5.“8023”是何意思?8023,第一次听到这个数字,以为是手机的验证码,或者以为是手机号码后四位,但是当你真正了解8023背后的含义是,或许你会留下感动的泪水。 我国的文化博大精深,源远流长,往往出现了很多有意思的数字组合,从而代表着不同的含义。把每个组合的背后,都深深地寄托着一份情感。 https://www.meipian.cn/4xp8c4sx
6.8023是什么8023网络梗词含义及解释近期各大弹幕视频中频繁出现的“8023”网络梗词解释成为了新的梗词,许多网友对此感到迷茫,为了帮助他们理解,我们整理了以下内容。 “8023”网络梗词解释 最近手机小视频又被8023刷屏了,估计好多人不知道8023什么意思。看到网上有人说,8023是代表一个80后,谈了23个女朋友;还有人说,8023意思是80后,2婚,3胎;更有人https://www.taicike.com/baike/24070.html
7.8023是什么意思8023的爱情含义→MAIGOO知识摘要:现在网上很流行一些数字梗,除了520、521这种通俗易懂的,还有一些手势梗,你知道都是什么意思吗?比如8023,很多小伙伴们问8023是什么意思,8023是一个表白手势语,它的爱情含义是我爱你LOVE,大家用手比划一下8023就知道它为什么代表我爱你。 8023是什么意思 https://www.maigoo.com/goomai/275403.html
8.揭秘8023一个网络用词背后的神秘含义在这个充满创意和活力的网络世界里,我们每天都会遇到各种各样的网络用词。有些词汇,如520、1314等,我们很容易理解其含义,但有一些词汇,如8023,可能会让我们感到困惑。那么,8023究竟是什么意思呢? 8023这个词汇在网络上并不常见,因此关于它的解释也五花八门,大多来自于网络用户的猜测和分享。然而,这些解释中并没有https://m.sohu.com/a/743660559_121769698/
9.8023的真正含义(女人为什么不接受8023)8023的真正含义(女人为什么不接受8023) 现在网上很流行数字梗,之前有说过1450、8426468、748541等。今天小编要和大家说的是8023,很多人会想问8023是什么意思啊?下面小编就来跟大家解释一下,感兴趣的朋友快来看看吧。 8023是什么意思啊 8023的意思是把你爱上,就是我爱你的意思。这是爱情物语书中的一个经典数字https://www.tjjntw.org.cn/news/2685.html
10.8023不能娶是什么意思8023有多少含义婚礼纪现代网络文化非常普及,特别是对于年轻人来说,网络中有许多流传已久的梗,特别是数字表白,也是在网络上火爆出圈的,8023不能娶是什么意思?8023有多少含义?一起跟随小犀来看看吧! 一、8023不能娶是什么意思 “8023不能娶”通常指的是性别相同的两个人在中国法律下不允许合法结婚。 https://www.hunliji.com/bai_ke/detail_81069
11.8023数字代表是什么意思?8023是什么网络用语?8023是什么网络用语? 经典手势语“LOVE” 最近,网上比较流行说8023告白梗,年轻人喜欢用“8023”来表达爱意。8023其实就是用手指比划数字: “8”:是把左手大拇指和食指叉开,竖放代表“L”。 “0”:代表“O”。 “2”:是叉开食指和中指,代表“V”。https://m.dbw.cn/shehui/system/2022/08/16/058956103.shtml
12.8023是什么意思啊8023是什么网络用语8023是什么意思啊-8023是什么网络用语 现在网上很流行数字梗,之前有说过1450、8426468、748541等。今天小编要和大家说的是8023,很多人会想问8023是什么意思啊?下面小编就来跟大家解释一下,感兴趣的朋友快来看看吧。 8023是什么意思啊 8023的意思是把你爱上,就是我爱你的意思。这是爱情物语书中的一个经典数字手语https://www.haha555.com/news/722.html
13.你知道“8023”的真正意思吗?不了解的,一定要看,否则就落伍了其实,8023这个梗来自于爱情物语书,是一个经典的数字手语,是最近网络上十分流行的网络用语,它的意思是无法舍弃的爱。 如果要翻译,8023也是有特定的含义:“把你爱上”。“8”的谐音是“把”,“0”谐音是“你”,“2”谐音是“爱”,“3”的谐音是“上”,合起来就是:把你爱上。 https://www.jianshu.com/p/16123b6f946b
14.以太网:电信网络的基石(以太网电信号)8023的含义是什么意思 802.3,这一看似简单的数字标识,实则代表了局域网通信的核心技术基石。 作为以太网标准的重要组成部分,它定义了数据在局域网中的传输规则,包括连接方式、速度规格、媒体类型以及网络操作协议。 它确保了各种以太网设备间的兼容性和互操作性,使得以太网成为当前最流行的本地网络技术。 https://www.ulidc.com/2024/12/14/%E4%BB%A5%E5%A4%AA%E7%BD%91%EF%BC%9A%E7%94%B5%E4%BF%A1%E7%BD%91%E7%BB%9C%E7%9A%84%E5%9F%BA%E7%9F%B3-%E4%BB%A5%E5%A4%AA%E7%BD%91%E7%94%B5%E4%BF%A1%E5%8F%B7/
15.英文字母V代表数字多少(字母V的含义)英文字母V代表数字多少(字母V的含义) 嗨!我是一个有横梁的小番茄。 今天和大家分享一个有趣的梗。请检查一下! 最近几天,你的手机被“8023”刷屏了吗? 世界上最珍惜的数字不是520,不是1314,而是8023。一个十几秒的短视频传遍网络,但很多人都有一个共同的疑问:“8023”是什么意思?http://www.zzfmdn.com/article/278847
16.网络语言中8023是什么意思?580230;i8023u 即为 我爱你。 8023手势图8023也可以做lose, 失去的含义,8依然是手语的L,0依然是https://wenwen.soso.com/z/q904982355.htm