美文网首页
浅谈JavaScript的Event-Loop

浅谈JavaScript的Event-Loop

作者: 沐源山 | 来源:发表于2020-01-17 10:35 被阅读0次

在之前的一篇文章中我们解释了一下为什么JavaScript要设计成单线程以及这门语言的任务队列的概念,这也帮助了我们简单了解了这门语言的运行机制,那么今天我们就谈谈任务队列相关的概念!

事件和回调函数

任务队列其实是事件的一个队列,也可以理解为消息队列,当IO设备完成一个任务的时候,就会在任务队列中添加一个事件,用来表示当前任务已经执行完了,可以进入执行栈(也就是之前讲过的主线程队列)了,主线程读取任务队列也就是读取有哪些事件!

任务队列中的事件除了IO设备之外,还有用户点击、键盘事件等,只要指定过回调函数,这些事件发生时就会进入任务队列,然后等待主线程读取。

回调函数(callback)其实就是被主线程挂起来的代码,主线程执行异步任务,其实就是执行回调函数!

任务队列其实是一个先进先出的数据结构,也就是说排在前面的事件会被优先读取,当主线程的代码执行完,执行栈被清空以后,就会立即执行任务队列中排在最前面的事件,但是由于定时器的功能,因此,主线程需要检查一下执行时间,某些事件只有等到规定的时间,才可以返回主线程!

Event Loop

主线程从任务队列读取事件这个过程是循环不断的,因此整个过程又被称为Event Loop(事件循环)

setTimeout(() => {
  console.log('timeout1');
}, 0)
console.log(1);
setTimeout(() => {
  console.log('timeout2');
}, 0)
console.log(2);
// 1 2 timeout1 timeout2

上面代码中有两个定时器,定时器也会放在任务队列中,因此我们常说在js中定时器可以模拟异步,其实是js默认会把定时器放在任务队列,前面我们讲过,js先会执行主线程的代码,称为执行栈,当执行栈的代码执行结束,执行栈清空之后才会执行任务队列中的代码, 因此上面的代码不会因为定时器在前面,而先执行定时器,当定时器的间隔时间一致时,按照添加顺序,先进任务队列则先执行!

NodeJs的Event Loop

NodeJs也是单线程的Event Loop,但是它区别于浏览器的运行环境;
在Nodejs中提供了process.nextTice()和setImmediate()两个与任务队列有关的方法;

process.nextTice()就是在当前执行栈尾部添加任务,也就是任务队列(所有的异步任务)开始之前;

console.log(1);
setTimeout(function timeout() {
  console.log('timeout1');
}, 0);

process.nextTick(function() {
  console.log(3);
  process.nextTick(function(){
    console.log(4);
  });
});

setTimeout(function timeout() {
  console.log('timeout2');
}, 0);

console.log(2);

// 1 2 3 4 timeout1 timeout2

setImmediate()会在每一次Event Loop结束执行,或者说下一次Event Loop执行之前执行

console.log('start');
setTimeout(function() {
    console.log('timeout1');
}, 0);
setImmediate(function (){
    setImmediate(function() {
        console.log(1);
        setTimeout(function() {
            console.log('timeout3');
        }, 0);
        setImmediate(function(){
            console.log(2);
        });
    });
    setTimeout(function() {
        console.log('timeout2');
    }, 0);
});
process.nextTick(function() {
    console.log('nextTick1');
    process.nextTick(function() {
        console.log('nextTick2')
    })
})
console.log('end');
// start end nextTick1 nextTick2 timeout1 1 timeout2 2 timeout3

上面代码前三个输出结果在没有其他干扰,就目前代码,不用质疑,主线程肯定先执行,接下来为nextTick,因为它会被放在所有异步执行之前,不论是否嵌套(不包括嵌套在其他异步函数中),timeout1在主线程程中被添加到任务队列,不论它是否在start之后还是end之前,它是区别于其他函数的唯一一个在任务队列顶端的函数,而setImmediate总会在一个Event Loop之后执行!

下篇我们我们聊聊任务队列中的微任务和宏任务!

相关文章

  • 浅谈JavaScript的Event-Loop

    在之前的一篇文章中我们解释了一下为什么JavaScript要设计成单线程以及这门语言的任务队列的概念,这也帮助了我...

  • 事件循环(Event loop):微任务(microtasks)

    意译 https://javascript.info/event-loop 浏览器和Node.js的JavaScr...

  • js事件机制与Promise

    (ps:不对之处,敬请指正!!!) Event-Loop 众所周知,JavaScript是单线程的,不知是哪个天才...

  • JS的Event-Loop

    javascript中的Event-Loop 在之前的一篇文章中我们解释了一下为什么JavaScript要设计成单...

  • 浅谈event-loop

    其实这是一篇很久之前就想发的博客了,最近有时间正好整理了下,我们先看一张图: 其中Memory Heap是内存分配...

  • js异步

    弄懂js异步 讲异步之前,我们必须掌握一个基础知识-event-loop。 我们知道JavaScript的一大特点...

  • javaScript macro-task(宏任务)与micro

    弄懂js异步 讲异步之前,我们必须掌握一个基础知识-event-loop。 我们知道JavaScript的一大特点...

  • JavaScript Math对象和Date对象浅谈

    JavaScript Math对象和Date对象浅谈 Math 对象 JavaScript当中的Math对象是原...

  • 2018-01-20

    浅谈,JavaScript 运行机制和Event Loop JavaScript是一个非常灵活的语言且是单线程所谓...

  • javascript中的事件循环event-loop

    线程 javascript是单线程的语言,也就是说,同一个时间只能做一件事。而这个单线程的特性,与它的用途有关,作...

网友评论

      本文标题:浅谈JavaScript的Event-Loop

      本文链接:https://www.haomeiwen.com/subject/gbswqctx.html