node.js中對(duì)Event Loop事件循環(huán)的理解與應(yīng)用實(shí)例分析
本文實(shí)例講述了node.js中對(duì)Event Loop事件循環(huán)的理解與應(yīng)用。分享給大家供大家參考,具體如下:
javascript是單線程的,所以任務(wù)的執(zhí)行都需要排隊(duì),任務(wù)分為兩種,一種是同步任務(wù),一種是異步任務(wù)。
同步任務(wù)是進(jìn)入主線程上排隊(duì)執(zhí)行的任務(wù),上一個(gè)任務(wù)執(zhí)行完了,下一個(gè)任務(wù)才會(huì)執(zhí)行。
異步任務(wù)是不進(jìn)入主線程,而是進(jìn)入一個(gè) "任務(wù)隊(duì)列" 里,"任務(wù)隊(duì)列" 通知主線程,該異步任務(wù)才會(huì)進(jìn)入主線程執(zhí)行。
任務(wù)的運(yùn)行機(jī)制如下:
1、所有同步任務(wù)在主線程上執(zhí)行,形成一個(gè) "執(zhí)行棧",注意棧是先進(jìn)后出的。
2、主線程外,有一個(gè) "任務(wù)隊(duì)列" ,只要異步任務(wù)處理完有結(jié)果了,就在 "任務(wù)隊(duì)列" 中放置一個(gè)事件,注意隊(duì)列是先進(jìn)先出的。
3、一旦 "執(zhí)行棧" 中所有同步任務(wù)執(zhí)行完畢。系統(tǒng)讀取 "任務(wù)隊(duì)列" 中的事件,對(duì)應(yīng)的異步任務(wù)。放入 "執(zhí)行棧" 中,開始執(zhí)行。
4、主線程不斷重復(fù)第三步,這種循環(huán)從 "任務(wù)隊(duì)列" 中讀取事件處理的這種運(yùn)行機(jī)制稱為Event Loop(事件循環(huán))。
"執(zhí)行棧" 中的同步代碼總是比 "任務(wù)隊(duì)列"中的異步任務(wù)之前運(yùn)行。
function fun() { setTimeout(function () { console.log('異步任務(wù)'); }, 0); console.log(1); console.log(2); console.log(3); console.log(4); console.log(5); } fun();
上面的代碼,console.log代碼寫在setTimeout后面,但仍然先執(zhí)行。
"任務(wù)隊(duì)列" 是一個(gè)隊(duì)列,隊(duì)列的特性是先進(jìn)先出??聪旅娲a:
function fun() { console.log(1); setTimeout(function () { console.log(2); setTimeout(function () { console.log(3); }, 0); }, 0); console.log(4); } fun();
輸出結(jié)果為 1 4 2 3,打印 2 的setTimeout任務(wù)比打印 3 的setTimeout任務(wù)先進(jìn)入隊(duì)列,所以會(huì)先運(yùn)行。
對(duì)于異步操作,像ajax,只有操作成功后返回結(jié)果,才會(huì)進(jìn)入 "任務(wù)隊(duì)列" 中,而不是調(diào)用的時(shí)候就放入隊(duì)列中??聪旅娲a:
<!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 誰先進(jìn)入隊(duì)列,誰先輸出,是需要看兩者消耗時(shí)間,誰更短。時(shí)間短的會(huì)先進(jìn)入隊(duì)列先運(yùn)行。
setTimeout 與 setInterval 運(yùn)行機(jī)制一樣,都是在指定時(shí)間把事件插入到 "任務(wù)隊(duì)列" 尾部。區(qū)別是前者只執(zhí)行一次,后者可反復(fù)執(zhí)行。
node.js 還為我們提供了,process.nextTick 和 setImmediate 與 "任務(wù)隊(duì)列" 有關(guān)的方法。
process.nextTick 會(huì)把回調(diào)函數(shù)放在當(dāng)前 "執(zhí)行棧" 的尾部。也就是說是在讀取 "任務(wù)隊(duì)列" 之前運(yùn)行。
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();
上面的代碼會(huì)輸出 1 6 3 5 4 2 ,注意process.nextTick會(huì)把回調(diào)函數(shù)放在 "執(zhí)行棧" 的尾部。
同步代碼最先輸出 1 6,然后 3 的先放入尾部,然后 5 的跟在 3 后面。3先執(zhí)行,然后把 4 放入到 5 的后面。5執(zhí)行完后,再執(zhí)行4,最后讀取 "任務(wù)隊(duì)列" 中的輸出2。
setImmediate 會(huì)把回調(diào)函數(shù)放在當(dāng)前 "任務(wù)隊(duì)列" 的尾部。也就是下一次事件循環(huán)Event Loop時(shí)執(zhí)行。
function fun() { console.log(1); setTimeout(function () { console.log(2); }, 0); setImmediate(function () { console.log(3); }); console.log(4); } fun();
上面的代碼是會(huì)輸出 1 4 2 3 還是 1 4 3 2 是不確定的,因?yàn)閟etTimeout 與 setImmediate 都會(huì)在下一次事件循環(huán)Event Loop中觸發(fā),所以輸出是不確定的。
希望本文所述對(duì)大家node.js程序設(shè)計(jì)有所幫助。
相關(guān)文章
Nodejs+express+ejs簡(jiǎn)單使用實(shí)例代碼
本篇文章主要介紹了Nodejs+express+ejs簡(jiǎn)單使用實(shí)例代碼,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-09-09Windows系統(tǒng)下使用Sublime搭建nodejs環(huán)境
最近在研究Nodejs開發(fā),俗話說,工欲善其事,必先利其器,當(dāng)然要找到一款用著順手的編輯器作為開始。這里我們選擇的是Sublime Text 3,除了漂亮的用戶界面,最吸引我的就是它的插件擴(kuò)展功能以及跨平臺(tái)特性。2015-04-04Node實(shí)戰(zhàn)之不同環(huán)境下配置文件使用教程
這篇文章主要給大家介紹了關(guān)于Node實(shí)戰(zhàn)之不同環(huán)境下配置文件使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01詳解webpack打包nodejs項(xiàng)目(前端代碼)
這篇文章主要介紹了webpack打包nodejs項(xiàng)目(前端代碼),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-09-09從零開始學(xué)習(xí)Node.js系列教程四:多頁面實(shí)現(xiàn)的數(shù)學(xué)運(yùn)算示例
這篇文章主要介紹了Node.js多頁面實(shí)現(xiàn)的數(shù)學(xué)運(yùn)算,涉及nodejs請(qǐng)求響應(yīng)、數(shù)值傳遞、運(yùn)算等相關(guān)操作技巧,需要的朋友可以參考下2017-04-04Node.js如何實(shí)現(xiàn)注冊(cè)郵箱激活功能 (常見)
今天了解了node如何實(shí)現(xiàn)郵箱激活功能,這個(gè)功能非常常見,當(dāng)我們注冊(cè)一個(gè)賬號(hào)時(shí),肯定會(huì)有這步,下面看下如何實(shí)現(xiàn)這個(gè)功能2017-07-07node?puppeteer爬蟲爬取電影網(wǎng)站及生成pdf文檔示例
這篇文章主要介紹了node?puppeteer爬蟲爬取電影網(wǎng)站及生成pdf文檔使用示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07Node.js中的events事件模塊知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家整理的是一篇關(guān)于Node.js中的events事件模塊知識(shí)點(diǎn)總結(jié)內(nèi)容,有興趣的朋友們可以跟著學(xué)習(xí)下。2021-12-12