美文网首页程序员
一篇文章读懂JavaScript的EventLoop

一篇文章读懂JavaScript的EventLoop

作者: 似水牛年 | 来源:发表于2018-05-10 17:38 被阅读0次

    JavaScript的单线程

    众所周知JavaScript程序是单线程的执行,也就是说,同一时刻只能做一件事,这也是由于JavaScript本身就是为了浏览器而生,主要用途是用户交互和操作dom,为什么是单线程?试想如果两个线程同时操作一个dom结点,那页面页面该怎样渲染,是不是会出问题呢?

    同步任务/异步任务

    虽然是单线程执行,但是JavaScript本身是包含同步和异步的两种任务的,也就是说,如果一个任务耗时很长,那我们可以把这个任务放到异步去执行,后面的任务就不用等待这个任务结束,就可以执行了。

    • 同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
    • 异步任务:不进入主线程、而进入任务队列(task queue)的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

    EventLoop

    说完了同步任务和异步任务,那JavaScript是用怎样的机制调度执行这两种任务的呢?这里就引入了EventLoop(事件循环),我们先看下一JavaScript的引擎模型:


    js-eventloop.png

    下面我们来说明一下引擎模型的几个重要部分

    • stack 栈
      JavaScript的函数调用形成了一个栈帧,执行前函数先入栈,执行完后函数出栈;
      Undefined、Null、Boolean、Number 和 String,这5中基本数据类型可以直接访问,他们是按照值进行分配的,存放在栈(stack)内存中的简单数据段,数据大小确定,内存空间大小可以分配。
    • heap 堆
      对象被分配在堆中,即用以表示一个大部分非结构化的内存区域
    • callback queue 消息队列
      一个 JavaScript 运行时包含了一个待处理的消息队列。每一个消息都有一个为了处理这个消息相关联的函数。

    EventLoop运行机制

    1. 所有同步任务都在主线程上执行,形成一个执行栈,如若遇到了一些异步操作像回调函数以及ajax、setTimeout等,会先将他们交给浏览器的其他模块去执行。
    2. 异步操作执行完成,就到消息队列中排队,等待执行。
    3. 一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取消息队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
    4. 主线程不断重复上面的第三步。

    从代码执行顺序的角度来看,程序最开始是按代码顺序执行代码的,遇到同步任务,立刻执行;遇到异步任务,则只是调用异步函数发起异步请求。此时,异步任务开始执行异步操作,执行完成后到消息队列中排队。程序按照代码顺序执行完毕后,查询消息队列中是否有等待的消息。如果有,则按照次序从消息队列中把消息放到执行栈中执行。执行完毕后,再从消息队列中获取消息,再执行,不断重复。由于主线程不断的重复获得消息、执行消息、再取消息、再执行。所以,这种机制被称为事件循环。

    事件循环讲完了,写一段代码测试一下,用最简单的setTimeout函数模拟异步操作,具体地理解一下事件循环的机制:

    setTimeout(function(){console.log("1")}, 1000);
    setTimeout(function(){console.log("5")}, 5000);
    setTimeout(function(){console.log("2")}, 2000);
    setTimeout(function(){console.log("0")});
    console.log("abc");
    

    执行结果如下,你理解事件循环了吗?

    abc
    0
    1
    2
    5
    

    相关文章

      网友评论

        本文标题:一篇文章读懂JavaScript的EventLoop

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