zoukankan      html  css  js  c++  java
  • Evevt Loop、任务队列、定时器等

    上周五,一个朋友发给我一道面试题,代码如下:

    console.log(1);
    setTimeout(console.log(2), 0);
    Promise.resolve().then(res => {
    	console.log(3);
    }).then(res=>{
    	console.log(4);
    })
    console.log(5);
    

    朋友说在控制台跑完的结果是依次打印出 1 2 5 3 4,但是不清楚为什么,希望我帮他分析下。


    额,我觉得setTimeout里的那个打印,是在下次事件循环时才会执行的,所以打印结果应该是 1 5 2 3 4 。。。。。

    然而,结果并非如此。说明我还处于朦胧状态啊,于是乎,开始去网上找博客。

    以下内容均是在博客中看到的内容,加上一点点自己的理解,至于是否客观正确,这个另说哈,时间会检验一切的。


    JS主要用来操作DOM,如果是多线程,会比较混乱,所以是单线程的。

    同步:主线程上执行的任务。

    异步:进入任务队列 的任务,只有等主线程上的任务执行完了,任务队列中的任务才会进入主线程执行。


    浏览器中的事件循环--Event Loop(我盗的图 哈哈)

    主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。

    从上图看到(下面这段也是抄的):

    1. 主线程运行的时候产生堆(heap)和栈(stack)
    2. 执行栈中的代码调用各种外部API,它们在"任务队列"中加入各种事件(click,load,done)
    3. 只要执行栈中的代码执行完毕,主线程就会去读取"任务队列",将队列中的事件放到执行栈中依次执行。
    4. 主线程继续执行,当再调用外部API时又加入到任务队列中,等主线程执行完毕又会接着将任务队列中的事件放到主线程中。
    5. 上面整个过程是循环不断的。

    不知道从哪引用的

    除了setTimeout和setInterval这两个方法,Node.js还提供了另外两个与"任务队列"有关的方法:process.nextTick和setImmediate。
    
    process.nextTick方法可以在当前"执行栈"的尾部----下一次Event Loop(主线程读取"任务队列")之前----触发回调函数。也就是说,它指定的任务总是发生在所有异步任务之前。 
    setImmediate方法则是在当前"任务队列"的尾部添加事件,也就是说,它指定的任务总是在下一次Event Loop时执行,这与setTimeout(fn, 0)很像。
    

    结论

    其实还有很多东西没有好好整理出来,下面只是大概记录下,详细的内容,查看下面的博文链接哈

    如果在原来的setTimeout console外面包了function。执行结果是1 5 3 4 2。

    首先,1 5 是同步任务,所以主线程中执行,setTimeout属于宏任务,添加到任务队列中,Promise是异步的,属于微任务,在同步任务执行完毕后执行,并且它也是链式的,所以它的回调函数会依次被添加到微任务中,微任务会在任务队列中的每一个task执行完后执行


    总之,setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,尽可能早得执行。它在"任务队列"的尾部添加一个事件,因此要等到同步任务和"任务队列"现有的事件都处理完,才会得到执行。

    HTML5标准规定了setTimeout()的第二个参数的最小值(最短间隔),不得低于4毫秒,如果低于这个值,就会自动增加。在此之前,老版本的浏览器都将最短间隔设为10毫秒。另外,对于那些DOM的变动(尤其是涉及页面重新渲染的部分),通常不会立即执行,而是每16毫秒执行一次。这时使用requestAnimationFrame()的效果要好于setTimeout()。

    需要注意的是,setTimeout()只是将事件插入了"任务队列",必须等到当前代码(执行栈)执行完,主线程才会去执行它指定的回调函数。要是当前代码耗时很长,有可能要等很久,所以并没有办法保证,回调函数一定会在setTimeout()指定的时间执行。

    But,还有个问题没搞明白:
    setTimeout( function(){ console.log(2) }, 0 );

    setTimeout( console.log(2), 0 );
    有啥子区别呢?执行结果不一样呢

    参考:

    你真的了解Event Loop(事件环)吗?
    JavaScript 运行机制详解:再谈Event Loop

  • 相关阅读:
    MySQL "show users"
    MySQL
    A MySQL 'create table' syntax example
    MySQL backup
    MySQL show status
    Tomcat, pathinfo, and servlets
    Servlet forward example
    Servlet redirect example
    Java servlet example
    How to forward from one JSP to another JSP
  • 原文地址:https://www.cnblogs.com/clover77/p/9204590.html
Copyright © 2011-2022 走看看