js事件循环

75 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第14天,点击查看活动详情

大家好,我是木大木大,因为疫情和环境原因啊,最近在看前端的面试题了,一些东西总是搞不明白,写出来看看,希望大家多多支持,莫嫌弃啦~ 。

事件循环

JavaScript的事件循环机制,首先需要知道两点:1.JavaScript是单线程语言;2.Event Loop是JavaScript的执行机制

那么JavaScript为什么是单线程语言呢?

单线程就是指JavaScript只能在一个线程上运行,同一时间只能执行一个任务,其他任务只能排队等待。

js的单线程主要是因为它作为脚本语言,主要的用途就是与用户交互,以及操作DOM。这就决定了js只能是单线程,一步一步操作,否则会带来复杂的同步问题。

什么是同步函数和异步函数呢?

同步行为对应内存中顺序执行的处理器指令。每条指令都会严格按照它们出现的顺序来执行,而每条指令执行后也能立即获得存储在系统本地(如寄存器或系统内存)的信息。这样的执行流程容易分析程序在执行到代码任意位置时的状态。

异步行为类似于系统中断,即当前进程外部的实体可以触发代码执行。异步操作经常是必要的,因为强制进程等待一个长时间的操作通常是不可行的(同步操作则必须要等)。如果代码要访问一些高延迟的资源,比如向远程服务器发送请求并等待响应,那么就会出现长时间的等待。

console.log('1');
​
setTimeout(function() {
  console.log('setTimeout');
}, 0);
​
Promise.resolve()(function() {
  console.log('promise1');
}).then(function() {
  console.log('promise2');
});
​
console.log('2');
​
如代码所示结果是1,promise1,2,promise2,setTimeoutconsole.log('1')
console.log('2')
Promise.resolve()(function() {
  console.log('promise1');
这些就是同步函数
setTimeout(function() {
  console.log('setTimeout');
}, 0);
    .then(function() {
  console.log('promise2');
});
那么这些就是异步函数咯

js 异步执行的运行机制。

  • 所有任务都在主线程上执行,形成一个执行栈。
  • 主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
  • 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列"。那些对应的异步任务,结束等待状态,进入执行栈并开始执行。
  • 主线程不断重复上面的第三步。

宏任务和微任务

宏任务(macro-task)主要是:script代码段、setTimeout、setInterval、Promise的构造函数是同步的、setImmediate、I/O、UIrendering

微任务(micro-task)主要是:Promise的回调、process.nextTick

事件循环(Event Loop)

事件循环其实就是入栈出栈的循环。上面例子中说到了setTimeout,那setInterval呢,Promise呢等等等等,有很多异步的函数。但是这些异步任务有分宏任务(macro-task)和微任务(micro-task):

每一次Event Loop触发时:

  1. 执行完主执行线程中的任务也就是执行第一个macro-task任务,例如script任务。
  2. 取出micro-task中任务执行直到清空。
  3. 取出macro-task中一个任务执行,直到清空。
  4. 重复执行。