趣谈js中的消息队列和事件循环

其实这个题目,应该是工作至少三年以上的大佬才可以谈论的,我这个工作了还不到一年的菜鸟,今天来聊一聊,为啥呢,我从学习前端开始就一直对这个东西比较迷惑哈。
不管是学习异步函数,微任务和宏任务 总会听到这个消息队列
期间也一直想听听那些老师们和大佬们讲一讲 这个东西到底是怎么回事 以及 js中的执行 到底是怎么回事 但是每次总是满怀期待的等着 可是 老师们讲的总的让我得不到满足,不是一笔带过,就是这个是js中的执行过程就是这样

也算是博主心中的一块心病吧,总是喜欢探究一些原理性的东西 搞不明白的话 总觉得没有学到根本性的东西 一直在表面浮动,虽然自己智商普普通通但是,深究原理也是我的兴趣之一,悬着的大石头也想一直搬走。
// 这里写下一些 学习心得吧
这里让我们重新认识下js吧
JavaScript ( JS ) 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。

JavaScript有一个基于事件循环的并发模型,事件循环负责执行代码、收集和处理事件以及执行队列中的子任务

下面是比较形象的 可视化模型
趣谈js中的消息队列和事件循环_第1张图片
这里也有三个核心概念:栈 堆 队列

1.函数调用形成了一个由若干帧组成的栈

在大学学过数据结构的同学可能知道,栈是先进后出的
我们这里看一段函数

function foo(b){
     
    var a=3;
    return a+b;
}

function bar(){
     
    let c=4;
    return foo(c);
}

console.log(bar());//返回 7

bar 函数先执行 那么 他就形成一个帧 然后压入栈中 帧中包括它内部定义的 局部变量c 然后继续往下面执行 碰见了 foo函数的执行
那么 foo 调用也形成了一个帧 压入栈中 (这里包括传入的参数b和局部变量c) 当foo 执行完毕之后 返回 a+b的结果 然后这个帧就从栈中 弹出来 然后在执行bar bar这个执行帧 也执行完毕之后 也就会被弹出来 此刻栈就被清空了

  1. 再来说说 堆这个东西 在js中常听到 js中的一些引用类型对象就存储在堆中 而变量只是存储着他们指向堆中的地址罢了,对象被分配在堆中,堆是一个用来表示一大块(通常是非结构化的)内存区域的计算机术语

  2. 消息队列 (队列是先进先出的
    在js执行的时候,会产生一个待处理的消息队列,每一个消息对应着一个待处理的回调函数。
    这里是关键

事件循环 期间的某个时刻,运行时会从最先进入队列的消息开始处理队列中的消息。被处理的消息会被移出队列,并作为输入参数来调用与之关联的函数。正如前面所提到的,调用一个函数总是会为其创造一个新的栈帧。

函数的处理会一直进行到执行栈再次为空为止;然后事件循环将会处理队列中的下一个消息(如果还有的话)

这里要联想 我前面说的 函数的调用形成的那个帧的问题

因为一个消息 对应一个回调函数, 当该消息要被触发的时候 ,那么消息就会被提出消息对立,因为消息队列是等待被处理的,而不是正在处理的。然后刚刚被踢出的 那个消息对应的回调函数就会被调用,压入栈中,当然这个回调函数内部也可能有其他的函数调用,当这个函数内部所有的帧压入栈中之后,然后依次执行完成,再依次弹出栈,当栈中清空的时候 表示 这个消息正式被执行完毕,

此刻就会询问 消息队列中是否还有等待的消息,有的话就进入(事件循环
因为js是单线程,所以同一时候 只能有一个消息在处理,不可能同时存在两个消息在处理,

但js还有一个很大的特点就是 不会阻塞代码执行
JavaScript的事件循环模型与许多其他语言不同的一个非常有趣的特性是,它永不阻塞。 处理 I/O 通常通过事件和回调来执行,所以当一个应用正等待一个 IndexedDB 查询返回或者一个 XHR 请求返回时,它仍然可以处理其它事情,比如用户输入。

好了 暂时说到这里 之后还会添加新的东西 关注我持续更新前端知识 加油

你可能感兴趣的:(javascript,js)