node.js中对Event Loop事件循环的理解与应用实例分析
本文实例讲述了node.js中对event loop事件循环的理解与应用。分享给大家供大家参考,具体如下:
javascript是单线程的,所以任务的执行都需要排队,任务分为两种,一种是同步任务,一种是异步任务。
同步任务是进入主线程上排队执行的任务,上一个任务执行完了,下一个任务才会执行。
异步任务是不进入主线程,而是进入一个 "任务队列" 里,"任务队列" 通知主线程,该异步任务才会进入主线程执行。
任务的运行机制如下:
1、所有同步任务在主线程上执行,形成一个 "执行栈",注意栈是先进后出的。
2、主线程外,有一个 "任务队列" ,只要异步任务处理完有结果了,就在 "任务队列" 中放置一个事件,注意队列是先进先出的。
3、一旦 "执行栈" 中所有同步任务执行完毕。系统读取 "任务队列" 中的事件,对应的异步任务。放入 "执行栈" 中,开始执行。
4、主线程不断重复第三步,这种循环从 "任务队列" 中读取事件处理的这种运行机制称为event loop(事件循环)。
"执行栈" 中的同步代码总是比 "任务队列"中的异步任务之前运行。
function fun() { settimeout(function () { console.log('异步任务'); }, 0); console.log(1); console.log(2); console.log(3); console.log(4); console.log(5); } fun();
上面的代码,console.log代码写在settimeout后面,但仍然先执行。
"任务队列" 是一个队列,队列的特性是先进先出。看下面代码:
function fun() { console.log(1); settimeout(function () { console.log(2); settimeout(function () { console.log(3); }, 0); }, 0); console.log(4); } fun();
输出结果为 1 4 2 3,打印 2 的settimeout任务比打印 3 的settimeout任务先进入队列,所以会先运行。
对于异步操作,像ajax,只有操作成功后返回结果,才会进入 "任务队列" 中,而不是调用的时候就放入队列中。看下面代码:
<!doctype html> <html lang="zh-cn"> <head> <meta charset="utf-8"> <title>title</title> </head> <body> <script> function ajax() { var xhr = new xmlhttprequest(); xhr.open('get', 'https://mail.163.com/', true); xhr.send(); xhr.onreadystatechange = function () { if (xhr.readystate == 4 && xhr.status == 200) { console.log(xhr.responsetext); } }; } function fun() { console.log(1); ajax(); settimeout(function () { console.log(2); }, 1000); console.log(3); } fun(); </script> </body> </html>
ajax() 与 settimeout 谁先进入队列,谁先输出,是需要看两者消耗时间,谁更短。时间短的会先进入队列先运行。
settimeout 与 setinterval 运行机制一样,都是在指定时间把事件插入到 "任务队列" 尾部。区别是前者只执行一次,后者可反复执行。
node.js 还为我们提供了,process.nexttick 和 setimmediate 与 "任务队列" 有关的方法。
process.nexttick 会把回调函数放在当前 "执行栈" 的尾部。也就是说是在读取 "任务队列" 之前运行。
function fun() { console.log(1); settimeout(function () { console.log(2); }, 0); process.nexttick(function () { console.log(3); process.nexttick(function () { console.log(4); }); }); process.nexttick(function () { console.log(5); }); console.log(6); } fun();
上面的代码会输出 1 6 3 5 4 2 ,注意process.nexttick会把回调函数放在 "执行栈" 的尾部。
同步代码最先输出 1 6,然后 3 的先放入尾部,然后 5 的跟在 3 后面。3先执行,然后把 4 放入到 5 的后面。5执行完后,再执行4,最后读取 "任务队列" 中的输出2。
setimmediate 会把回调函数放在当前 "任务队列" 的尾部。也就是下一次事件循环event loop时执行。
function fun() { console.log(1); settimeout(function () { console.log(2); }, 0); setimmediate(function () { console.log(3); }); console.log(4); } fun();
上面的代码是会输出 1 4 2 3 还是 1 4 3 2 是不确定的,因为settimeout 与 setimmediate 都会在下一次事件循环event loop中触发,所以输出是不确定的。
希望本文所述对大家node.js程序设计有所帮助。
上一篇: 猪腰怎么焯水才嫩
下一篇: 鸡爪要煮多少分钟才熟透