zoukankan      html  css  js  c++  java
  • JavaScript 异步、栈、事件循环、任务队列

    概览

    我们经常会听到引擎和runtime,它们的区别是什么呢?

    • 引擎:解释并编译代码,让它变成能交给机器运行的代码(runnable commands)。
    • runtime:就是运行环境,它提供一些对外接口供Js调用,以跟外界打交道,比如,浏览器环境、Node.js环境。不同的runtime,会提供不同的接口,比如,在 Node.js 环境中,我们可以通过 require 来引入模块;而在浏览器中,我们有 window、 DOM。

    Js引擎是单线程的,如上图中,它负责维护任务队列,并通过 Event Loop 的机制,按顺序把任务放入栈中执行。而图中的异步处理模块,就是 runtime 提供的,拥有和Js引擎互不干扰的线程。接下来,我们会细说图中的:栈和任务队列

    现在,我们要运行下面这段代码:

    function bar() {
        console.log(1);
    }
    
    function foo() {
        console.log(2);
        far();
    }
    
    setTimeout(() => {
        console.log(3)
    });
    
    foo();


    它在栈中的入栈、出栈过程,如下图:

    任务队列

    Js 中,有两类任务队列:宏任务队列(macro tasks)和微任务队列(micro tasks)。宏任务队列可以有多个,微任务队列只有一个。那么什么任务,会分到哪个队列呢?

    • 宏任务:script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering.
    • 微任务:process.nextTick, Promise, Object.observer, MutationObserver.

    我们上面讲到,当stack空的时候,就会从任务队列中,取任务来执行。共分3步:

    1. 取一个宏任务来执行。执行完毕后,下一步。
    2. 取一个微任务来执行,执行完毕后,再取一个微任务来执行。直到微任务队列为空,执行下一步。
    3. 更新UI渲染。

    Event Loop 会无限循环执行上面3步,这就是Event Loop的主要控制逻辑。其中,第3步(更新UI渲染)会根据浏览器的逻辑,决定要不要马上执行更新。毕竟更新UI成本大,所以,一般都会比较长的时间间隔,执行一次更新。

    从执行步骤来看,我们发现微任务,受到了特殊待遇!我们代码开始执行都是从script(全局任务)开始,所以,一旦我们的全局任务(属于宏任务)执行完,就马上执行完整个微任务队列。看个例子:

    console.log('script start');
    
    Promise.resolve().then(() => {
        console.log('p 1');
    });
    
    setTimeout(() => {
        console.log('setTimeout');
    }, 0);
    
    var s = new Date();
    while(new Date() - s < 50); // 阻塞50ms
    
    Promise.resolve().then(() => {
        console.log('p 2');
    });
    
    console.log('script ent');
    
    
    /*** output ***/
    
    // one macro task
    script start
    script ent
    
    // all micro tasks
    p 1
    p 2
    
    // one macro task again
    setTimeout



    上面之所以加50ms的阻塞,是因为 setTimeout 的 delayTime 最少是 4ms. 为了避免认为 setTimeout 是因为4ms的延迟而后面才被执行的,我们加了50ms阻塞。在微任务中,process.nextTick 是一个特殊的任务,它会被直接插入到微任务的队首(当然了,多个process.nextTick 之间也是先入先出的),优先级最高。


    来源:https://segmentfault.com/a/1190000011198232
    
    
  • 相关阅读:
    EXTJS 4.2 资料 控件之checkboxgroup的用法(静态数据)
    EXTJS 4.2 资料 控件之Window窗体相关属性的用法
    EXTJS 4.2 资料 控件之textfield文本框加事件的用法
    Entity Framework 学习笔记(一)之数据模型 数据库
    EXTJS 4.2 资料 控件之checkboxgroup的用法(动态数据)
    EXTJS 4.2 资料 控件之Grid 列鼠标悬停提示
    Entity Framework 学习笔记(二)之数据模型 Model 使用过程
    EXTJS 4.2 资料 控件之radiogroup 的用法
    EXTJS API
    vue移动端弹框组件,vue-layer-mobile
  • 原文地址:https://www.cnblogs.com/liangzhixiaolaohu/p/8580372.html
Copyright © 2011-2022 走看看