EVent Loop

作者: YangJeremy | 来源:发表于2018-03-28 15:33 被阅读0次

    单线程

    JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。

    如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。

    主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。

    于是,任务分成了两种,一种是同步任务,一种是异步任务

    同步任务

    在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;
    

    异步任务

    不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
    
    

    所谓"回调函数"(callback),就是那些会被主线程挂起来的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。

    "任务队列"是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。

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

    Node.js的Event Loop

    (1)V8引擎解析JavaScript脚本。
    
    (2)解析后的代码,调用Node API。
    
    (3)libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎。
    
    (4)V8引擎再将结果返回给用户。
    
    

    process.nextTick方法可以在当前"执行栈"的尾部----下一次Event Loop(主线程读取"任务队列")之前----触发回调函数。也就是说,它指定的任务总是发生在所有异步任务之前。

    process.nextTick(function A() {
      console.log(1);
      process.nextTick(function B(){console.log(2);});
    });
    
    setTimeout(function timeout() {
      console.log('TIMEOUT FIRED');
    }, 0)
    // 1
    // 2
    // TIMEOUT FIRED
    
    

    由于process.nextTick方法指定的回调函数,总是在当前"执行栈"的尾部触发,所以不仅函数A比setTimeout指定的回调函数timeout先执行,而且函数B也比timeout先执行。这说明,如果有多个process.nextTick语句(不管它们是否嵌套),将全部在当前"执行栈"执行。

    相关文章

      网友评论

        本文标题:EVent Loop

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