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

  • 相关阅读:
    手机市场价格尚待规范
    Hotmail的2G邮箱被收回,只剩250M了
    网格50题(zz)
    Wallop介绍
    Hotmail邮箱居然还有2G
    IE 7.0抛弃Win2000用户?(zz)
    祝各位Blogger新春快乐!
    Gmail Invitation
    A CS Research Topic Generator(zz)
    今天"做大岁"
  • 原文地址:https://www.cnblogs.com/clover77/p/9204590.html
Copyright © 2011-2022 走看看