javaScript运行机制及Event Loop

js时单线程语言

  • 因为js的主要用途是【与用户互动以及操作DOM】,故js只能是单线程。
  • 为了利用多核CPU的计算能力,H5提出Web Worker标准,允许js脚本创建多个线程,但是子线程完全受主线程控制,且不得操作DOM。

任务队列

  • 单线程,意味着要有【任务队列】(task queue)
  • 所有【任务】分为两种:
    • 【同步任务】(在【主线程】上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务)
    • 【异步任务】(不进入主线程,而进入任务队列的任务)
  • 异步执行的运行机制
    • 所有同步任务都在主线程上执行,形成一个【执行栈】;
    • 主线程之外,还存在一个【任务队列】。只要异步任务有了运行结果,就在任务队列中放置一个事件;
    • 一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列中的事件,与之对应的异步任务就结束等待状态,进入执行栈,开始执行;
    • 主线程不断重复第三步;

【小结】:
js的运行机制:只要主线程空了,就回去读取任务队列。


事件和回调函数

  • 任务队列是一个事件的队列,即消息队列。IO设备完成一项任务,就在任务队列中添加一个事件,表示相关的异步任务可以进入执行栈了。主线程读取任务队列中的事件。
  • 任务队列中的事件:IO设备事件,用户操作产生的事件。
  • 【回调函数】:会被主程序挂起的代码。异步任务必须指定回调函数,当主线程开始执行异步任务,就是执行对应的回调函数。
  • 【任务队列】:先进先出。

Event Loop

这里写图片描述

  • 主线程运行时,产生【堆】和【栈】,栈中的代码调用各种【外部API】,它们在【任务队列】中加入【事件】。只要栈中的代码执行完毕,主线程就回去读取任务队列,依次执行哪些事件所对应的【回调函数】。
  • 执行栈中的代码【同步任务】,总是在读取任务队列【异步任务】之前执行。

定时器

  • 任务队列中可放:异步任务的事件、定时事件
  • 【定时器功能】:定时执行的代码,setTimeoutsetTimeInterval
  • setTimeout(fn, t)的含义是:指定某个任务在主线程最早可得的空闲时间执行,尽可能早地执行。它在任务队列的尾部添加一个事件,因此要等到同步任务和任务队列现有的事件都处理完,才会得到执行。
  • HTML5规定了setTimeout的time参数的最小值,若低于4毫秒,就会自动增加。另外,对于DOM的变动通常不会立即执行,而是每16毫秒执行一次。
  • setTimeout()只是将事件插入了任务对垒,必须等到当前代码执行栈执行完,主线程才会去执行它指定的回调函数。若当前代码耗时很长可能要等很久,所以并不能保证回调函数一定会在setTimeout()指定的时间执行。

Nodejs环境下

执行过程:

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

(未完待续)

猜你喜欢

转载自blog.csdn.net/sunxiaofre/article/details/78508120