js事件运行机制

js是单线程的

js是单线程的,也就是说,同一个时间只能做一件事情。
原因:作为浏览器的脚本语言,js的主要用途是与用户进行交互,以及操作dom,所以如果有多线程的话,一个线程在某个节点上操作dom,另外一个节点在删除dom,就不知道以哪个线程为准。
单线程意味着所有任务都需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。例如ajax请求,需要等到网络有响应了才返回数据(IO操作)。
JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面
的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。
同步任务进入主线程,而异步任务进入任务队列,不进入主线程,只有任务队列通知了主线程,某个异步任务执行完成了,该任务才会进入主线程。
执行流程如下:
1.所有同步任务都在主线程上执行,形成一个执行栈,
2.主线程之外,还存在一个任务队列,只要异步任务有了结果,就在任务队列中放置一个事件。
3一旦执行栈中所有同步任务都执行完毕后,系统就会读取”任务队列“,看看里面有些什么事件,那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
4.主线程不断重复上面的第三步。
只要主线程空了,就会去读取”任务队列”,这就是JavaScript的运行机制。这个过程会不断重复。

事件和回调函数

任务队列是一个事件的队列,IO设备(用户产生事件,例如鼠标点击等),只要指定了回调函数,这些事件发生时就会进入”任务队列”,等待主线程读取。
回调函数的含义:(被主线程挂起来的代码),异步任务必须指定回调函数,当主线程执行异步任务,就会执行对应的回调函数。
“任务队列”是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上是自动的,只要执行栈一清空,”任务队列”上第一位的事件就自动进入主线程。但是,由于存在后文提到的”定时器”功能,主线程首先要检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。

event loop

主线程运行的时候,产生堆和栈。栈中的代码调用各种外部API,它们在”任务队列”中加入各种事件(click,load,done)。只要栈中的代码执行完毕,主线程就会去读取”任务队列”,依次执行那些事件所对应的回调函数。
setTimeOut的含义:指定某个任务在主线程得到的最早空闲时间执行,也就是说,尽可能早的执行,任务队列的尾部添加一个事件,因此等到同步任务和任务队列所有事件处理完,才会得到执行。
node的后续再说
(参考链接)[http://www.ruanyifeng.com/blog/2014/10/event-loop.html]