精华内容
下载资源
问答
  • 主要介绍了JS事件循环机制event loop宏任务微任务原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 事件循环机制 Event Loop 文章目录事件循环机制 Event Loop一.JavaScript是单线程1.为什么JavaScript是单线程2.让JavaScript拥有多线程二.任务队列1.同步任务(synchronous)2 异步任务(asynchronous)2.1 异步任务的...

    事件循环机制 Event Loop

    一.JavaScript是单线程

    Javascript语言是的一大特点是单线程,也就是说每次只能执行一项任务,其他任务都得按照顺序排队等待被执行,只有当前的任务执行完成之后才会执行下一个任务.

    1.为什么JavaScript是单线程

    ​ 为什么JavaScript是单线程的?根据阮一峰大神介绍,作为浏览器的脚本语言,JavaScript的主要用途是与用户互动,以及进行DOM操作.这决定了它只能是单线程.否则会带来很多复杂的同步问题.比如,JavaScript同时有2个线程,一个线程在DOM节点上添加内容,另一个线程删除了这个DOM节点,那么请问,这个时候浏览器应该以哪个线程为准呢?

    2.让JavaScript拥有多线程

    ​ 为了利用多核CPU的计算能力,HTML5提出了Web Worker标准,允许JavaScript脚本创建多个线程,但是子线程完全受主线程控制.并且还不能操作DOM,所以,这个新标准,并没有改变JavaScript是单线程的本质.

    二.任务队列

    单线程就意味着,所有的任务都需要排队,前面一个任务结束,才会执行后一个任务.如果前一个任务耗时很长,后一个任务就不得不一直等着

    任务分为2种:

    1.同步任务(synchronous)

    同步任务是指:在主线程上排队执行的任务,只有当前一个任务执行完毕,才能执行后一个任务

    var num = 0;
    console.log('任务一');
    for (let index = 0; index < 100000000; index++) {
        num += index;
    }
    console.log(num);
    console.log('任务二');
    

    以上代码是一个同步任务.当任务一执行之后,进入for循环去计算,但是这个for循环计算需要很长的时间,所以不得不等着,只有当for循环计算完成之后,才可以去执行任务二,这种形式的任务,就是同步任务.

    2 异步任务(asynchronous)

    异步任务是指:不进入主线程,而是进入任务队列,只有任务队列通知主线程,某个异步任务可以执行了,那么该任务才会进入主线程执行.

    console.log('任务一');
    setTimeout(() => {
        console.log('任务二');
    }, 3000);
    console.log('任务三');
    //打印结果:任务一 > 任务三 > 任务二
    

    以上代码是一个异步任务.不按顺序执行,同时执行多个任务.因为setTimeout是一个异步任务,所以会先执行同步任务,然后再执行异步任务

    所以呢,可以得到一个结论:同步任务和异步任务同时存在时,一定先执行完同步任务再执行异步任务.

    setTimeout(() => {
        console.log('任务一');
    }, 0);
    console.log('任务二');
    var num = 0;
    for (let index = 0; index < 100000000; index++) {
        num += index;
    }
    console.log(num);
    console.log('任务三');
    
    执行结果:
    任务二
    4999999950000000
    任务三
    任务一
    
    

    从上面代码可以看出,setTimeout这个异步任务不管写在哪里,都会先执行同步任务,再执行异步任务

    2.1 异步任务的执行机制

    同步任务执行也可以这么认为,因为它可以被视为没有异步任务的异步执行

    • 所有同步任务都在主线程上执行,形成一个执行栈
    • 主线程之外,还存在一个"任务队列",只要异步任务有了运行结果,就在"任务队列"之中放置一个事件
    • 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件.哪些对应的异步任务,于是结束等待状态,进入执行栈,开始执行
    • 主线程不断的重复上面这一步

    3.Javascript中的异步任务

    3.1 setTimeout和 setInterval
    setTimeout(function() { console.log(‘b’); }, 10)
    
    3.2 dom事件
    console.log("1")
    dom.onclick = function () { alert(123) }
    console.log("2")
    

    Javascript中的事件基本上都是异步的,上面代码,会先执行同步代码,打印结果1,2之后,等待触发点击事件后,才会执行,所以也是个异步任务

    3.3 ajax

    ajax请求,不用说了,都知道,它是异步请求数据

    3.4 promise
    var promise = new Promise(function(resolve, reject) {//这里是同步任务
        console.log(3);
        resolve();
    })
    promise.then(function() {//这里是异步任务
        console.log(4);
    })
    

    4.调用栈 Call Stack(执行栈)

    调用栈是一种后进先出的数据结构,当一个脚本执行的时候,js引擎会解析这段代码,并将其中同步代码按照执行顺序加入调用栈中,然后从头开始执行.

    在谷歌浏览器中,我们F12调试的时候,可以看到右边的 Call Stack,也就是调用栈,所有的代码都会进出于这个调用栈.

    后进先出的意思是:就像子弹壳装弹,一粒一粒的进去,但是打出来的时候,是从上面打出来的,最先压进去的最后弹出来,也就是说进去的顺序的123,打出来的顺序是321,这就是后进先出.

    5.事件队列(Task Queue)

    ​ js引擎遇到一个异步任务之后,并不会一直等待其返回结果,而是会将这个任务交给浏览器的其他模块进行处理(以谷歌浏览器的webkit为例,是webcore模块) 继续执行调用栈中的其他任务.当一个异步任务返回结果后,js引擎会将这个任务加入与当前调用栈不同的另一个队列,我们称之为事件队列也有叫"任务队列".

    三.事件循环机制

    在这里插入图片描述

    我们来解读下这个图:

    call stack :当一个脚本执行的时候,js引擎会解析这段代码,并且将其中的同步代码按照执行顺序加入调用栈中,然后从头开始执行.

    webcore module: js引擎遇到一个异步事件后并不会一直等待其返回结果,而是将这个事件挂起(其他模块进行处理),继续执行调用栈中的其他任务.一个异步事件返回结果后,js会将这个事件加入到事件队列.

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

    在这里插入图片描述

    • 整体的script(作为第一个宏任务),开始执行的时候,会把所有代码分为两部分:同步任务和异步任务
    • 同步任务会直接进入主线程依次执行
    • 异步任务会再分为宏任务和微任务
    • 宏任务进入到Event Table中,并在里面注册回调函数,每当指定的事件完成时,Event Table会将这个函数移入大Event Queue中
    • 微任务也会进入到另一个Event Table中,并在里面注册回调函数,每当指定的事件完成时,Event Table会将这个函数移到Event Queue中
    • 当主线程内的任务执行完毕,主线程为空时,会检查微任务的Event Queue,如果有任务,就全部执行,如果没有就执行下一个宏任务.所以,先执行微任务在执行宏任务

    上述过程会不断重复,这就是Event Loop事件循环

    四.微任务和宏任务

    上面说的事件循环过程是一个宏观的表述,实际上因为异步任务之间并不相同,因此他们的执行优先级也有区别.

    不同的异步任务被分为两类:

    微任务(micro task):
    promise.then、promise.nextTick(node),MutationObserver(html5 新特性)
    宏任务(macro task)
    整体代码script、setTimeout、setInterval......

    需要注意的是:new Promise是会进入到主线程中立刻执行,而promise.then则属于微任务

    先执行整体的宏任务,再执行异步任务中的微任务,然后执行宏任务

    五.示例代码解读

    1.示例一

    console.log(1);
    var timer = setTimeout(function () {//异步任务的宏任务
        console.log(2);
    }, 0)
    console.log(timer);//延时器的id 值为1
    var promise = new Promise(function (resolve, reject) {//同步任务
        console.log(3);
        resolve();
    })
    promise.then(function () { //异步任务的微任务
        console.log(4);
    })
    console.log(5);
    //1,1,3,5,4,2
    

    2.示例二

    async function async1() {
        console.log('async1 start');
        await async2();
        console.log('async1 end');
    }
    async function async2() {
        console.log('async2');
    }
    console.log('script start');
    setTimeout(function() {
        console.log('setTimeout');
    }, 0)
    async1();
    new Promise(function(resolve) {
        console.log('promise1');
        resolve();
    }).then(function() {
        console.log('promise2');
    });
    console.log('script end');
    

    先执行宏任务(当前代码块也算是宏任务),然后执行当前宏任务产生的微任务,然后接着执行宏任务

    1. 从上往下执行代码,先执行同步代码,输出 script start
    2. 遇到setTimeout,现把 setTimeout 的代码放到宏任务队列中
    3. 执行 async1(),输出 async1 start, 然后执行 async2(), 输出 async2,把 async2() 后面的代码 console.log('async1 end')放到微任务队列中
    4. 接着往下执行,输出 promise1,把 .then()放到微任务队列中;注意Promise本身是同步的立即执行函数,.then是异步执行函数
    5. 接着往下执行, 输出 script end。同步代码(同时也是宏任务)执行完成,接下来开始执行刚才放到微任务中的代码
    6. 依次执行微任务中的代码,依次输出 async1 endpromise2, 微任务中的代码执行完成后,开始执行宏任务中的代码,输出 setTimeout

    最后的执行结果如下

    • script start
    • async1 start
    • async2
    • promise1
    • script end
    • async1 end
    • promise2
    • setTimeout

    3.示例三

    console.log('start');
    setTimeout(() => {
        console.log('children2');
        Promise.resolve().then(() => {
            console.log('children3');
        })
    }, 0);
    
    new Promise(function(resolve, reject) {
        console.log('children4');
        setTimeout(function() {
            console.log('children5');
            resolve('children6')
        }, 0)
    }).then((res) => {
        console.log('children7');
        setTimeout(() => {
            console.log(res);
        }, 0)
    })
    

    这道题跟上面题目不同之处在于,执行代码会产生很多个宏任务,每个宏任务中又会产生微任务

    1. 从上往下执行代码,先执行同步代码,输出 start
    2. 遇到setTimeout,先把 setTimeout 的代码放到宏任务队列①中
    3. 接着往下执行,输出 children4, 遇到setTimeout,先把 setTimeout 的代码放到宏任务队列②中,此时.then并不会被放到微任务队列中,因为 resolve是放到 setTimeout中执行的
    4. 代码执行完成之后,会查找微任务队列中的事件,发现并没有,于是开始执行宏任务①,即第一个 setTimeout, 输出 children2,此时,会把 Promise.resolve().then放到微任务队列中。
    5. 宏任务①中的代码执行完成后,会查找微任务队列,于是输出 children3;然后开始执行宏任务②,即第二个 setTimeout,输出 children5,此时将.then放到微任务队列中。
    6. 宏任务②中的代码执行完成后,会查找微任务队列,于是输出 children7,遇到 setTimeout,放到宏任务队列中。此时微任务执行完成,开始执行宏任务,输出 children6;

    最后的执行结果如下

    • start
    • children4
    • children2
    • children3
    • children5
    • children7
    • children6

    4.示例四

    const p = function() {
        return new Promise((resolve, reject) => {
            const p1 = new Promise((resolve, reject) => {
                setTimeout(() => {
                    resolve(1)
                }, 0)
                resolve(2)
            })
            p1.then((res) => {
                console.log(res);
            })
            console.log(3);
            resolve(4);
        })
    }
    
    
    p().then((res) => {
        console.log(res);
    })
    console.log('end');
    
    1. 执行代码,Promise本身是同步的立即执行函数,.then是异步执行函数。遇到setTimeout,先把其放入宏任务队列中,遇到p1.then会先放到微任务队列中,接着往下执行,输出 3
    2. 遇到 p().then 会先放到微任务队列中,接着往下执行,输出 end
    3. 同步代码块执行完成后,开始执行微任务队列中的任务,首先执行 p1.then,输出 2, 接着执行p().then, 输出 4
    4. 微任务执行完成后,开始执行宏任务,setTimeout, resolve(1),但是此时 p1.then已经执行完成,此时 1不会输出。

    最后的执行结果如下

    • 3
    • end
    • 2
    • 4
    展开全文
  • Event Loop事件循环机制 事件循环机制Event Loop)是全面了解javascript代码执行顺序绕不开的一个重要知识点。 为什么会有事件循环机制? javascript从诞生之日起就是一门单线程的非阻塞的脚本语言。这是由其最初...
  • EventLoop 事件循环机制

    2021-02-13 09:46:00
    原因之一在于当初也是最主要的执行环境 —浏览器中,在浏览器中,我们需要执行各种各样的dom操作,试想一下,如果是多线程的,那么两个或者多个线程对同一dom操作时,比如一个向其添加事件,另一个删除了这个dom,...

     

    一.  JavaScript是一门单线程非阻塞的脚本语言(这是由最初的用途所决定:与浏览器交互)

    1. 单线程

           JavaScript语言的一大特点是单线程,为何是单线程呢?原因之一在于当初也是最主要的执行环境 —浏览器中,在浏览器中,我们需要执行各种各样的dom操作,试想一下,如果是多线程的,那么两个或者多个线程对同一dom操作时,比如一个向其添加事件,另一个删除了这个dom,此时就会出现问题了。为了保证不会发生类似的情况,JavaScript选择只用一个主线程来执行代码,也就是说,每次只能执行一项任务,其他任务都得按照顺序排队等待被执行,只有当前的任务执行完成之后,才会执行下一个任务。

           当然,现如今人们也意识到,单线程在保证执行顺序的同时,也限制了JavaScript的效率,因此开发出了web worker技术(这项技术号称让JavaScript成为一门多线程语言),但是使用web worker这项技术开的多线程也存在很多限制,例如:所有新线程都受主线程的完全控制,不能独立执行。这意味着这些“线程” 实际上应属于主线程的子线程。另外,这些子线程并没有执行I/O操作的权限,只能为主线程分担一些诸如计算等任务。所以严格来讲这些线程并没有完整的功能,也因此这项技术并非改变了javascript语言的单线程本质。

          2.非阻塞

            非阻塞则是当代码需要进行一项异步任务(无法立刻返回结果,需要花一定时间才能返回的任务,如I/O事件)的时候,主线程会挂起(pending)这个任务,然后在异步任务返回结果的时候再根据一定规则去执行相应的回调。非阻塞是通过事件循环机制实现的。 JS通常是非阻塞的,除了某些特殊情况,JS会停止代码执行,比如:

           1.   alert, confirm, prompt(除了Opera)

           2.   “页面上的程序正忙”的系统对话框弹出

    二. 浏览器中的js事件循环机制

         1. 任务队列

            所有的任务可以分为同步任务和异步任务,同步任务,顾名思义,就是立即执行的任务,同步任务一般会直接进入到主线程中执行;而异步任务,就是异步执行的任务,比如ajax网络请求,setTimeout 定时函数等都属于异步任务,异步任务会通过任务队列( Event Queue )的机制来进行协调。 同步和异步任务分别进入不同的执行环境,同步的进入主线程,即主执行栈,异步的进入 Event Queue 。主线程内的任务执行完毕为空,会去 Event Queue 读取对应的任务,推入主线程执行。 上述过程的不断重复就是我们说的 Event Loop (事件循环)。

          如下图所示:

           同步和异步任务分别进入不同的执行环境,同步的进入主线程,即主执行栈,异步的进入任务队列。主线程内的任务执行完毕为空,会去任务队列读取对应的任务,推入主线程执行。 上述过程的不断重复就是我们说的 Event Loop (事件循环)。

     2.事件循环     

        在事件循环中,每进行一次循环操作称为tick,每一次 tick 的任务处理模型是比较复杂的,其关键的步骤可以总结如下:

    1. 执行栈选择最先进入队列的宏任务(通常是script整体代码),开始执行宏任务 ---------------------------------------------宏任务微任务在下面👇
    2. 检查是否存在微任务( Microtasks ),如果存在则不停地执行,直至清空微任务队列(Microtask Queue)

    3. 更新 render(每一次事件循环,浏览器都可能会去更新渲染)

    4. 主线程重复执行上述步骤

        我们可以认为任务队列执行优先级: 同步 > 微任务 > 宏任务

        如下图所示:

    3. 宏任务与微任务

        异步任务分为 宏任务(macrotask) 与 微任务 (microtask)

         1.宏任务

             script(整体代码)、setTimeout、setInterval、UI 渲染、 I/O、postMessage、 MessageChannel、setImmediate(Node.js 环境)

         2.微任务

             Promise、 MutaionObserver、process.nextTick(Node.js环境)

    三. 举例(面试常谈)

    1.  先来个简单的

    console.log('script start');
     
    setTimeout(function() {
      console.log('setTimeout');
    }, 0);
     
    Promise.resolve().then(function() {
      console.log('promise1');
    }).then(function() {
      console.log('promise2');
    });
    console.log('script end');
    

    输出结果

     

    2.稍微增加点难度

    setTimeout(()=>{
       console.log(1) 
    },0)
    let a=new Promise((resolve)=>{
        console.log(2)
        resolve()
    }).then(()=>{
       console.log(3) 
    }).then(()=>{
       console.log(4) 
    })
    console.log(5) 
    // 输出
    //2 5 3 4 1
    

    3.再复杂一些

    new Promise((resolve,reject)=>{
        console.log("promise1")
        resolve()
    }).then(()=>{
        console.log("then11")
        new Promise((resolve,reject)=>{
            console.log("promise2")
            resolve()
        }).then(()=>{
            console.log("then21")
        }).then(()=>{
            console.log("then23")
        })
    }).then(()=>{
        console.log("then12")
    })
    

    输出结果

        

    4.难度++

    async function async1() {
        console.log("async1 start");
        await  async2();
        console.log("async1 end");
    }
    async  function async2() {
        console.log( 'async2');
    }
    console.log("script start");
    setTimeout(function () {
        console.log("settimeout");
    },0);
    async1();
    new Promise(function (resolve) {
        console.log("promise1");
        resolve();
    }).then(function () {
        console.log("promise2");
    });
    console.log('script end'); 
    

    输出结果

    展开全文
  • JavaScript 事件循环机制Event Loop)简述 单线程的 JavaScript Web Worker 任务队列 运行机制 事件回调 事件循环(Event Loop) 单线程的 JavaScript JavaScript 是浏览器的脚本语言。其主要作用是与客户端...

    单线程的 JavaScript

    JavaScript 是浏览器的脚本语言。其主要作用是与客户端进行交互。最开始设计之初它就是单线程。因为它主要操作 DOM。如果设计成多线程,假设一个线程在操作某个 DOM 节点,一个线程又在删除这个 DOM 节点。这时候浏览器就无法判断以哪个线程为主,这种复杂的场景大大增加了语言的难度。所以 JavaScript 从一诞生就是单线程。也是它最重要的特性之一。

    Web Worker

    在 HTML5 中提出了 Web Worker。其主要作用是为 JavaScript 提供多线程环境。主线程可以创建多个 Worker 子线程。但是 Web Worker 不能操作 DOM ,且不能影响主线程。所以也并没有改变 JavaScript 单线程的本质。只是为了有效利用多核 CPU,充分发挥计算机的计算能力。

    任务队列

    因为 JavaScript 是单线程,所以所有的任务只能一个个等着被执行。如果一个任务是被 CPU 一直占着倒也罢。但是有时候是 IO (输入输出设备)占用的时间比较长,而 CPU 处在空闲状态。那么为了有效利用 CPU。可以将 IO 设备耗时较长的任务挂起,先执行后面的任务。等到 IO 设备返回了结果,再回过头来执行挂起的任务。任务队列是一个先进先出的结构,排在前面的事件,优先进入主线程被执行。

    运行机制

    1. 所有的任务都在主线程执行,形成执行栈。
    2. 主线程之外,还有一个任务队列。系统将异步任务放在任务队列中。
    3. 等到主线程中的任务执行完成,系统就会读取任务队列中的任务。
    4. 异步任务结束了等待状态,就会从任务队列进入执行栈,恢复执行。
    5. 主线程重复以上步骤。

    事件回调

    除了常见的 IO 设备之外,用户交互(点击,滑动,触摸等)都会被添加到任务队列,等待主线程读取。IO 设备完成一项任务,就是在 “任务队列”中添加一个事件。表示相关的任务可以进入执行栈了。主线程读取任务队列,就是读取里面有哪些回调事件。
    回调函数就是被任务队列挂起的代码。异步任务必须指定回调函数。当异步任务从任务队列中回到执行栈,就是回调函数被执行的时候。

    事件循环(Event Loop)

    主线程运行的时候,会产生堆和栈。栈中的代码会调用各种外部 API。他们在任务队列中加入各种事件。只要栈中的代码执行完毕,主线程就会去读取“任务列队”,依次执行哪些事件所对应的回调函数。主线程从“任务队列”中读取事件,这个过程是循环不断的。所以叫事件循环机制。

    展开全文
  • 这个规则就是事件循环机制EventLoop)下面详细描述下。 javascript擎遇到一个异步事件后并不会一直等待其返回结果,而是会将这个事件挂起,继续执行执行栈中的其他任务。当一个异步事件返回结果后,js会将这个...

    首先清楚javaScript这门语言是一门单线程非阻塞的脚本语言。

    单线程是指在执行javascript代码的时候,只有一个主线程按照一定的顺序执行任务。
    非阻塞是指当代码需要进行一项异步任务,的时候,主线程会挂起这个任务,然后在异步结果返回时根据一定规则执行相应的回调。
    单线程的缺点也是很明显的,例如:

    • 同一时间只能执行一个任务,上一个任务执行完毕后,才可以执行下一个任务,阻塞代码执行,

    • cpu的利用率低,只能应用一部分cpu进行计算。

      但是使用单线程其实是有原因的,虽然使用单线程会使代码的执行效率低,但是,javascript这门脚本语言创造出来就是应用在路浏览器的交互和DOM的操作。如果多线程同时操作同一个dom元素的话,比如子线程修改dom元素,子线程B删除这个Dom元素,如果子线程B先执行完毕,那么子线程A修改dom元素就不成立,是个悖论。为防止这类事情发生,所以javascript定义为单线程。
      单线程执行代码是有顺序性和阻塞性的。遇到I/O操作等耗费事件较长的任务必须等待完成后执行下一个任务。所以javascript实现了一个新的特性异步回调

      所谓异步回调就是当主线程遇到I/O任务时,把当前任务挂起,放入事件队列继续执行下一个任务,当I/O任务处理完成后执行根据一定的规则执行这个任务的回调,然后再根据一定的规则回到主进程处理任务。
      这个规则就是事件循环机制(EventLoop)下面详细描述下。

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

    异步任务的类型

    异步任务有两种类型:微任务(micorotask)和宏任务(macrotack)。不同的类型的任务会放在不同的任务队列中,

    属于微任务的事件包括但不限于以下几种:

    • Posmise.then
    • MutationObserver
    • process.nextTick

    属于宏任务的事件包括但不限于以下几种:

    • setTimeout
    • setInterval
    • setImmediate
    • MessageChannel
    • resquestAnimationFrame
    • I/O
    • UI交互事件

    事件循环

    事件循环机制图解

    在这里插入图片描述
    代码执行过程首先代码开始按顺序执行,执行过程中遇到微任务,把他放入微任务队列中,遇到宏任务把他放入宏任务队列中。
    函数调用时, 先查看微任务队列中是否有可执行的微任务,如果没有则从宏任务中取出下一个宏任务执行,如果有可执行的微任务,则从微任务队列中按顺序执行微任务,执行完毕从微任务队列中删除,并从宏任务队列中取出下一个宏任务执行。然后宏任务执行完毕再次执行微任务对列的微任务,反复循环,形成事件循环。
    下面来道实例:

    console.log('start');
    setTimeout(function() { //setTimeout1
        console.log('setTimeout1');
        process.nextTick(function() {
            console.log('nextTick1'); //nextTick1
        })
        new Promise(function(resolve) {// Promise1
            console.log('Promise1');
            resolve();
        }).then(function() {
            console.log('Promise1.then')
        })
    })
    new Promise(function(resolve) { //Promise2
        console.log('Promise2');
        resolve();
    }).then(function() {
        console.log('Promise2.then')
    })
    
    setTimeout(function() {  //setTimeout2
        console.log('setTimeout2');
        process.nextTick(function() { //nextTick2
            console.log('nextTick2');
        })
        new Promise(function(resolve) {  //Promise3
            console.log('Promise3');
            resolve();
        }).then(function() {
            console.log('Promise3.then')
        })
    })
    
    

    第一次循环

    1. 首先执行console.log(‘1’);
      遇到setTimeout1,是宏任务,放入宏任务队列
      遇到Promise2,Promise里是立即执行函数,所以里面的代码会立即执行,代码会执行 console.log('Promise1)。Promise2.then,是微任务,放入微任务队列。
      遇到setTimeout2,宏任务,放入宏任务队列。

    在这里插入图片描述

    1. 查询微任务对列中有可执行的微任务,有Promise2.then,执行console.log(‘Promise2.then’)
      执行完毕微任务队列清空。开启下一个宏任务。

    第二次循环

    1. 执行宏任务setTimeout1,console.log(‘setTimeout1’);
      遇到process.nextTick为微任务,放入微任务队列。
      遇到Promise1,立即执行console.log(‘Promise1’),并把Promise1.then放入微任务队列。

    在这里插入图片描述

    1. 查询微任务队列中有可执行的微任务,有Promise1.then和process.nextTick1.
      执行 process.nextTick1, process.nextTick1从微任务队列删除。
      打印console.log(‘nextTick1’)
      ,执行Promise1.then,打印console.log(‘Promise1.then’)
      Promise1.then从微任务队列删除。
      宏任务setTimeout执行完毕,从宏任务队列删除。
      执行下一个宏任务。

    在这里插入图片描述

    第三次循环

    1. 执行宏任务setTimeout2, 打印 console.log(‘setTimeout2’);
      遇到process.nextTick2为微任务,放到微任务队列中 遇到Promise3立即执行 console.log(‘Promise3’);
      遇到 Promise3.then为微任务放到微任务队列中。
      在这里插入图片描述
    2. 查询微任队列中,有process.nextTick2和Promise3.then。
      执行process.nextTick2,打印 console.log(‘nextTick2’); 从微任务中删除process.nextTick2
      执行Promise3.then,打印 console.log(‘Promise3.then’) 从微任务中删除Promise3.then
      宏任务setTimeout2执行完毕,从宏任务队列中删除

    终止
    自此微任务队列与宏任务队列清空,循环结束。

    答案

    start
     Promise2
     Promise2.then
    setTimeout1
    nextTick1
     Promise1
     Promise1.then
    setTimeout2
    nextTick2
     Promise3
     Promise3.then
    

    2021.01.01
    新年的第一篇文章,多多支持。新年快乐。
    文章内容是自己理解,如果有一些不足和问题,希望不吝赐教。谢谢

    展开全文
  • 步骤二:一篇博文,深入了解事件循环机制:js事件循环机制(浏览器端Event Loop) 以及async/await的理解 步骤三:夯实基础,查漏补缺:Js 的事件循环(Event Loop)机制以及实例讲解 步骤四:一道面试题,检测所学: ...
  • js 事件循环Event Loop机制

    千次阅读 2018-05-06 16:03:24
    利用事件循环机制分割任务 function timeProcessArray(items,process,callback){ var todo = items.concat(); setTimeout(function(){ var start = +new Date(); do{ process(todo.shift()); }while(todo....
  • 主要介绍了JavaScript运行机制事件循环(Event Loop)详解,本文从多个方面讲解了Event Loop,需要的朋友可以参考下
  • 本人也是学了很久的JS来返回去学这个event loop的,终于搞懂了。 下面把这段分享给大家。 本文还要讲到宏队列与微队列,我们循序渐进的来学习。 event loop 我们需要先弄懂,进程与线程。 进程:程序的一次执行,他...
  • 深入剖析javascript的事件循环机制 Event loop

    千次阅读 多人点赞 2020-11-05 16:15:56
    如何js事件循环 是当前各大公司问的非常频繁的一个问题。很多人估计大概知道js事件循环是个什么东西,单可能在脑子里的概念又比较模糊,无法深入的理清楚。那么事件循环到底是个什么东西。今天我们来好好了解一下。
  • 标签: eventloop 事件机制 node 原文地址:Tasks, microtasks, queues and schedules 鉴于上篇文章有提到过 微任务与宏任务,所以,在此做个细致补充: 话不多说,直接进入正文: [1] 本文主要根据网上资源总结而...
  • 主要给大家介绍了关于前端js中事件循环eventloop机制的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用js具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
  • event loop的理解(event loop事件循环的运行机制) 前言 js是一种单线程的语言,所以它通过event loop机制实现了对异步任务和多线程。 首先你要对栈、队列的数据结构有一定的了解,其次还要会Promise才能看懂...
  • 在Netty的线程模型中,每个channel都有唯一的一个eventLoop与之相绑定,那么在这篇博文中我们来看一下EvenLoop及其相关概念。 在传统的Java NIO编程中,我们经常使用到如下代码: public static void main...
  • 详解JavaScript中的Event Loop事件循环机制

    千次阅读 多人点赞 2018-01-19 15:06:57
    前言我们都知道,...而非阻塞则是当代码需要进行一项异步任务(无法立刻返回结果,需要花一定时间才能返回的任务,如I/O事件)的时候,主线程会挂起(pending)这个任务,然后在异步任务返回结果的时候再根据一
  • JS的事件循环机制EventLoop JS是单线程的,事件循环机制简要为以下: 1.同步任务放在执行栈中,异步任务放在任务队列中 2.任务队列分为宏任务队列和微任务队列 3.执行完执行栈中的任务,再执行任务队列中的任务 4....
  • 2.js事件循环 除了广义的同步任务和异步任务,对任务更细致费划分: macro-task(宏任务):包括整体代码script,setTimeout,setInterval等 micro-task(微任务):Promise,process.nextTick等 js执行的时候: 第...
  • event loop到async await来了解事件循环机制 作者:船长_ 链接:https://juejin.im/post/5c148ec8e51d4576e83fd836 JS为什么是单线程的? 最初设计JS是用来在浏览器验证表单操控DOM元素的是一门脚本语言,如果js...
  • 优先级是调用栈 > 微任务 > 消息队列 // 调用栈 function func() { console.log("func");... }) func() /** * 执行结果 Promise func then setTimeout */ 参考 2分钟了解 JavaScript Event Loop | 面试必备
  • 事件循环机制Event Loop
  • 经典面试题----Eventloop事件循环

    千次阅读 2020-03-29 22:42:47
    Event Loop事件循环,是指浏览器或Node的一种解决javaScript单线程运行时不会阻塞的一种机制,也就是我们经常使用异步的原理。 JavaScript代码的执行过程中,除了依靠函数调用栈来搞定函数的执行顺序外,还依靠...
  • 主要介绍了Node.js事件循环Event Loop)和线程池详解,这篇文章比较浅显地探讨了有关事件循环的内部运作机制和技术细节,都是经过深思熟虑的,需要的朋友可以参考下
  • 都到一封私信,相信很多人对一些js运行机制,一看到都是很头疼的问题,那么博主今天彻底整理了一篇js运行机制类的问题,并且分段进行封装,哪里不会点哪里。 提示:以下是本篇文章正文内容,下面案例可供参考 一、...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 26,954
精华内容 10,781
关键字:

事件循环机制eventloop