美文网首页
js Event Loop 事件循环

js Event Loop 事件循环

作者: G_whk | 来源:发表于2019-05-06 15:54 被阅读0次
    前言

    javascript是一门单线程的非阻塞的脚本语言。这是由其最初的用途来决定的:与浏览器交互,单线程是必要的,也是javascript这门语言的基石,原因之一在其最初也是最主要的执行环境——浏览器中,我们需要进行各种各样的dom操作。试想一下 如果javascript是多线程的,那么当两个线程同时对dom进行一项操作,例如一个向其添加事件,而另一个删除了这个dom,此时该如何处理呢?因此,为了保证不会 发生类似于这个例子中的情景,javascript选择只用一个主线程来执行代码,这样就保证了程序执行的一致性。

    单线程意味着,javascript代码在执行的任何时候,都只有一个主线程来处理所有的任务。

    而非阻塞则是当代码需要进行一项异步任务(无法立刻返回结果,需要花一定时间才能返回的任务,如I/O事件)的时候,主线程会挂起(pending)这个任务,然后在异步任务返回结果的时候再根据一定规则去执行相应的回调。

    运行环境

    js运行环境总共两个:浏览器和node。

    概念:

    javascript代码执行的时候会将不同的变量存于内存中的不同位置:堆(heap)和栈(stack)中来加以区分。其中,堆里存放着一些对象。而栈中则存放着一些基础类型变量以及对象的指针。

    js是单线程的,同一时间只能执行一个方法,于是这些方法被排队在一个单独的地方。这个地方被称为执行栈。

    js引擎遇到一个异步事件后并不会一直等待其返回结果,而是会将这个事件挂起,继续执行执行栈中的其他任务。当一个异步事件返回结果后,js会将这个事件加入与当前执行栈不同的另一个队列,我们称之为事件队列。

    被放入事件队列不会立刻执行其回调,而是等待当前执行栈中的所有任务都执行完毕, 主线程处于闲置状态时,主线程会去查找事件队列是否有任务。如果有,那么主线程会从中取出排在第一位的事件,并把这个事件对应的回调放入执行栈中,然后执行其中的同步代码...,如此反复,这样就形成了一个无限的循环。这就是这个过程被称为“事件循环(Event Loop)

    运行机制

    1.一个主进程就是js引擎,其他均为辅助的线程。
    2.主进程存在一个执行栈,事件触发线程维护一个消息队列
    3.同步任务在执行栈中执行,异步任务在满足条件后加入到消息队列中,等待执行。
    4.先执行栈中的任务,执行完毕后,检查队列是否为空,不为空,将队列中的任务压入执行栈中执行。直到栈和队列均为空。

    看图加深记忆 image

    测试一下:

    setTimeout(function(){
        console.log(0)
    },500)
    
    console.log(a);
    

    上面这段代码用于不会有输出,同步代码死循环阻塞了执行栈。虽然定时后回调加入执行队列,但是异步永远不会执行。

    微任务(microtask jobs)和宏任务(macrotask task)

    浏览器环境下宏任务:setTimeout setImmediate MessageChannel 微任务:Promise.then MutationObserver
    node环境下的微任务和宏任务有哪些 宏任务:setTimeout setImmediate 微任务:Promise.then process.nextTick
    运行机制:

    1.微任务在宏任务之前的执行,先执行 执行栈中的内容 执行后 清空微任务
    2.每次取一个宏任务 就去清空微任务,之后再去取宏任务

    测试一下

    setTimeout(function(){
        console.log('setTimeout1');
        Promise.resolve().then(()=>{
            console.log('then1');
        });
    },0)
    Promise.resolve().then(()=>{
        console.log('then2');
        Promise.resolve().then(()=>{
            console.log('then3');
        })
        setTimeout(function(){
            console.log('setTimeout2');
        },0)
    })
    
    //then2 then3 setTimeout1 then1 setTimeout2
    

    node的下的执行特点
    1.为微任务,定时器,io,setImmidiate分别分配消息队列
    2.先检查定时器队列,如果有内容,则全部清空
    3.从时间队列切换到io队列的过程中,检查微任务,如果有则情况微任务。
    4.io队列执行完成,如果有check队列的内容,则执行。否则继续检查定时器队列,完成闭环。

    注意⚠️

    1.同样是微任务,process.nextTick,优于promise.then先执行
    2.同样是宏任务,setTimeout和setImediate执行的先后顺序是不确定的,依赖于执行栈执行的速度。

    相关文章

      网友评论

          本文标题:js Event Loop 事件循环

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