event loop线程

作者: 海娩 | 来源:发表于2017-10-24 07:24 被阅读98次

    参考:
    阮一峰event loop
    MDN Concurrency model and Event Loop
    阮一峰线程和进程概念
    javascript Event Loop机制详解

    线程和进程

    进程是指CPU所能处理的单个任务,任一时刻,CPU总是运行一个进程,而一个进程里可以有几个线程,几个线程同时进行,协同完成一个任务。

    什么是event loop??

    事件循环
    简单说,就是在程序中设置两个线程:一个负责程序本身的运行,称为”主线程”;另一个负责主线程与其他进程(主要是各种I/O操作)的通信,被称为”Event Loop线程”(可以译为”消息线程”)
    像javascript就是基于单线程的运行机制,这种模型与其他语言如c,java就有非常明显的区别。

    任务队列

    javascript的单线程就意味着所有的任务都需要排队,前一个执行完后一个才会执行。

    image.png

    这样看来,其实等待的时间甚至有时候会多于执行的时间,造成cpu空等并且后面的事项又很紧急等待的情况。
    这时,javascript语言的设计者就了解到,可以先挂起正在等待返回的任务,先执行后面的任务

    image.png

    于是,所有任务就可以分为两种,同步任务和异步任务。同步任务是指主线程上的任务,只有前一个任务执行完毕才能执行后一个任务;异步任务是指不进入主线程,进入’任务队列‘的任务。

    任务队列中的事件
    image.png

    像这样的机制通常运用在一些不是可以立即执行的,比如用户产生的时间,只要有指定回调函数,这些事件就会进入“任务队列”,等待主线程完成后进行读取。
    任务队列也是先进先出的数据结构。

    异步任务的事件

    除此之外,只要是有回调函数的事件,就几乎都是异步事件,会被放进任务队列中。拿setTimeout()事件来说,这是最经典的事件了。
    setTimeout()接收两个参数,第一个是回调函数,第二个是延迟时间
    然而,在下面的例子中你会发现,即使延迟时间为0,还是相同的结果,这就是因为任务队列中的事件需要在主线程完成之后再执行,通过这样我们也可以看到,如果主线程任务很多,定时器的延迟时间比较短,就会出现不准的情况。

        var m = 1;
        var n = 2;
        setTimeout(function() {
              console.log(m);
        }, 0);
        console.log(n);
    
        //2
        //1
    

    小试题

    在一篇帖子看到的,刚开始还想不明白ヽ(≧□≦)ノ。
    摘录下来。

        function foo() {
    console.log('1');
    bar();
    setTimeout(function() {
        console.log('2');
    }, 0);
    Promise.resolve().then(function() {
        console.log('3');
        Promise.resolve().then(function() {
            console.log('4');
        });
    });
    console.log('5');
    }
    
    function bar() {
    setTimeout(function() {
        console.log('6');
      }, 0);
    setTimeout(function() {
        console.log('7');
      }, 0);
    }
    
    foo();
    

    哈哈哈公布答案

    image.png
    Q:刚开始不明白的是为什么2是排在6和7的后面,明明bar()里面的setTimeout比直接setTimeout多一个调用级别?

    后来想到,在一次调用bar()后,进入bar()函数里面,就要把该函数里的进程运行结束才会返回,所以bar()函数里面的setTimeout要运行结束才会出来继续执行任务队列里接下来的其他任务。

    • 2 一个for循环添加事件

             function send(argument) {
            console.log(argument);
        }
        var m = document.getElementById('ok');
        for (var i = 0; i < 5; i++) {
            console.log(i);   //0,1,2,3,4
            m.addEventListener('click', function () {
                console.log(i)   //5,5,5,5,5
            }) 
        }
      
    这里看到不一样的输出结果,这有两方面的原因

    1 是因为var声明的变量存在变量提升的问题
    2 是因为js单线程所以动态添加事件的事件被挂起,直到主线程结束
    解决的办法很简单,把var改为let,就不存在变量提升的问题。或者也可以从事件挂起的角度出发,找其他的解决办法如闭包

    相关文章

      网友评论

        本文标题:event loop线程

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