js事件循环机制

1、为什么会有事件循环机制?

JavaScript是一种单线程的语言,这意味着它一次只能执行一个任务。然后,Web应用通常需要处理多个任务,比如用户输入,网络请求,渲染页面等。如果所有的任务都按照同步的方式执行,可能会导致阻塞页面,用户体验不佳。

为了解决这个问题,javascript引入了事件循环机制。事件循环是一种机制,用于管理和调度不同来源的任务执行。这个机制运行jsvascript在执行一部操作时不会阻塞整个应用程序的执行。

2、事件循环的关键组成部分

  1. 执行栈(Execution Stack): JavaScript 引擎使用执行栈来管理代码的执行。当调用函数时,会将该函数推入执行栈,并在执行完毕后从栈中弹出。
  2. 任务队列(Task Queue): 在事件循环中,除了执行栈外,还存在任务队列。当发生异步事件(如定时器结束、事件触发等)时,会将对应的回调函数放入任务队列中。
  3. 事件循环(Event Loop): JavaScript 引擎在执行栈为空时,会不断地从任务队列中取出任务,推入执行栈中执行。这个过程不断重复,形成了事件循环。

这个机制允许 JavaScript 在执行异步任务时,通过将回调函数放入任务队列中,在执行栈为空时再去执行这些任务,从而实现异步执行而不会阻塞整个程序。

3、事件循环执行步骤

  1. 先执行所有的同步任务:会有序依次向下执行的例如console,条件判断语句,循环语句等等。
  2. 执行异步任务里的微任务队列将解析到的微任务依次添加到微任务队列的后排,在执行时按顺序依次执行,先进先执行先出去例如Process.$nextTick,promise实例的then方法,await关键字
  3. 执行异步任务里的宏任务队列宏任务队列的执行是没有顺序之分的,哪个任务先调用完成就执行哪个任务(比如有一个5秒的定时器先加入进来的,但是有后加入进来一个2秒的定时器,那么2秒的定时器先调用完成,就先执行,所以是无序的),事件处理函数,定时器(setTimeout, setInterval),ajax请求,script标签

4、例子

//1、同步任务,会立即执行,马上输出
console.log("script start");

// 2、异步任务-》宏任务,推入宏任务队列中[事件2], 执行完全部同步任务和微任务队列后,才会执行
setTimeout(function() {
  console.log("setTimeout---0");
}, 0);

// 3、异步任务-》宏任务,推入宏任务队列中[事件2、事件3],执行完全部同步任务和微任务队列后,才会执行
setTimeout(function() {
  // 31、同步任务,会立即执行,马上输出
  console.log("setTimeout---200");
  // 32、异步任务-》宏任务,推入宏任务队列中[事件32],执行完全部同步任务和微任务队列后,才会执行
  setTimeout(function() {
    console.log("inner-setTimeout---0");
  });
  // 33、异步任务-》微任务,推入微任务队列中[事件33],执行完全部同步任务后,才会执行
  Promise.resolve().then(function() {
    console.log("promise5");
  });
}, 200);

// 4、异步任务-》微任务,推入微任务队列中[事件4],执行完全部同步任务后,才会执行
Promise.resolve()
  .then(function() {
    console.log("promise1");
  })
  .then(function() {
    console.log("promise2");
  });

// 5、异步任务-》微任务,推入微任务队列中[事件4、事件5],执行完全部同步任务后,才会执行
Promise.resolve().then(function() {
  console.log("promise3");
});

// 6、同步任务,会立即执行,马上输出
console.log("script end");

// 执行完所有同步任务后,会输出 : 'script start' -> 'script end'
// 接着执行异步任务的微任务队列[事件4、事件5](按顺序执行):会输出:'promise1' -> 'promise2' -> 'promise3'
// 接着执行异步任务的宏任务队列[事件2、事件3](无顺序执行,谁执行的快,就输入哪个),会输出:'setTimeout---0' -> 'setTimeout---200' -> 'promise5' -> 'inner-setTimeout---0'

// 结果
'script start'
'script end'
'promise1'
'promise2'
'promise3'
'setTimeout---0'
'setTimeout----200'
'promise5'
'inner-setTImeout0----0'

你可能感兴趣的:(javascript,开发语言,ecmascript)