JavaScript的异步运行机制

时间:2024-01-13 22:17:02

----异步运行机制如下:

1.左右同步任务都在主线程上执行,形成一个执行栈

2.主线程值外,还存在一个任务队列,只要异步任务有了运行结果,就在任务队列中放置一个事件

3.一旦执行栈中的所有同步任务执行完毕,系统会读取任务队列并将对应要执行的任务放到主线程中,主线程结束等待状态,进入执行栈,开始执行

(只要主线程空了,就会读取任务队列,这就是JavaScript运行机制,这个过程不断重复)

4.主线程重复以上步骤

----为什么JavaScript是单线程:

1.JavaScript一次只能做一件事,作为浏览器脚本语言,多个线程中进行的操作可能会造成冲突,所以JavaScript只能是单线程

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

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

----

"任务队列"是一个事件的队列(也可以理解成消息的队列),IO设备完成一项任务,就在"任务队列"中添加一个事件,表示相关的异步任务可以进入"执行栈"了。主线程读取"任务队列",就是读取里面有哪些事件。

"任务队列"中的事件,除了IO设备的事件以外,还包括一些用户产生的事件(比如鼠标点击、页面滚动等等)。只要指定过回调函数,这些事件发生时就会进入"任务队列",等待主线程读取。

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

"任务队列"是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上是自动的,只要执行栈一清空,"任务队列"上第一位的事件就自动进入主线程。但是,由于存在后文提到的"定时器"功能,主线程首先要检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。

----JavaScript中没有任何代码时立即执行的,都是进程空闲时尽快执行