您好,登錄后才能下訂單哦!
nodejs中怎么循環(huán)瀏覽器事件,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。
瀏覽器中的事件循環(huán):
為了協(xié)調(diào)事件(event),用戶交互(user interaction),腳本(script),渲染(rendering),網(wǎng)絡(luò)(networking)等,用戶代理(user agent)必須使用 事件循環(huán)(event loops).
事件:PostMessage(多個頁面通信),MutationObserver(dom監(jiān)聽)等
用戶交互:click,onScroll等
渲染:解析dom,css等
腳本:執(zhí)行腳本
nodejs中的事件循環(huán)
事件循環(huán)允許Node.js執(zhí)行非阻塞I/O操作,盡管JavaScript是單線程的,通過盡可能將操作卸載到系統(tǒng)內(nèi)核,由于大多數(shù)現(xiàn)代內(nèi)核都是多線程的,因此 他們可以處理在后臺執(zhí)行的多個操作。當其中一個操作完成時,內(nèi)核會告訴Nodejs,以便可以將相應(yīng)的回調(diào)添加到輪詢隊列中以最終執(zhí)行。
事件:EventEmitter
非阻塞I/O: 網(wǎng)絡(luò)請求,文件讀寫等
腳本: js執(zhí)行腳本
事件循環(huán)的本質(zhì)
在瀏覽器或者nodejs環(huán)境中,運行時對js腳本的調(diào)度方式就叫事件循環(huán)
setTimeout(()=>{ console.log('setTimeout') },0) Promise.resolve().then(() =>{ console.log('promise') }) console.log('main') // main promise setTimeout
javascript為什么是單線程的?
瀏覽器js的作用是操作DOM,這決定了它只能是單線程,否則會帶來很復雜的同步問題。比如,假定javascript同時有兩個線程,一個線程在某個DOM 節(jié)點上添加內(nèi)容,另一個線程刪除了這個節(jié)點,這時瀏覽器不知道以哪個線程為主。
任務(wù)隊列
單線程意味著所有任務(wù)需要排隊,如果因為任務(wù)cpu計算量大還好,但是I/O操作cpu是閑著的。所以js就設(shè)計成了一門異步語言,不會做無謂的等待。
任務(wù)可以分成兩種,一種是同步任務(wù),另一種是異步任務(wù)。
所有同步任務(wù)都在主線程上執(zhí)行,形成一個執(zhí)行棧。
主線程之外,還存在一個任務(wù)隊列。只要異步任務(wù)有了運行結(jié)果,就在任務(wù)隊列之中放置一個事件。
一旦執(zhí)行棧中的所有同步任務(wù)執(zhí)行完畢,系統(tǒng)就會讀取任務(wù)隊列,看看里面有哪些事件。那些對應(yīng)的異步任務(wù),于是結(jié)束等待狀態(tài),進入執(zhí)行棧,開始執(zhí)行。
主線程不斷重復上面的第三步
主線程從任務(wù)隊列中讀取事件,這個過程是循環(huán)不斷的,所以整個的這種運行機制又稱 Event Loop(事件循環(huán))
宏任務(wù)和微任務(wù)
除了廣義的同步任務(wù)和異步任務(wù),javaScript單線程中的任務(wù)可以細分為 宏任務(wù)和微任務(wù)。
macrotask(宏任務(wù)): script(整體代碼),setTimeout, setInterval, setImmediate, I/O, UI rendering
microtask(微任務(wù)):process.nextTick, Promise, Object.observe, MutationObserver 1.宏任務(wù)進入主線程,執(zhí)行過程中會搜集微任務(wù)加入微任務(wù)隊列。 2.宏任務(wù)執(zhí)行完成之后,立馬執(zhí)行微任務(wù)中的任務(wù)。微任務(wù)執(zhí)行過程中將再次收集宏任務(wù),并加入宏任務(wù)隊列 3.反復執(zhí)行1,2
事件循環(huán):每執(zhí)行完一輪宏任務(wù)和微任務(wù)就叫做一環(huán)事件;
一輪事件循環(huán)會執(zhí)行一次宏任務(wù)以及所有的微任務(wù)
setTimeout(() => { console.log('setTimeout') setTimeout(() => { console.log('setTimeout2') },0) },0) Promise.resolve().then(() =>{ console.log('Promise') Promise.resolve().then(() =>{ console.log('Promise2') }) }) console.log('main') // main promise promise2 setTimeout
任務(wù)隊列一定會保持先進先出的順序執(zhí)行,沒次只能執(zhí)行一個紅任務(wù)!??!·
setTimeout(() => { // 兩個setTimeout誰先進的話 誰就先出 console.log('setTimeout') Promise.resolve().then(() =>{ console.log('promise') }) },0) Promise.resolve().then(() =>{ console.log('promise2') setTimeout(() => { console.log('setTimeout2') },0) }) console.log('main') // main promise2 setTimeout promise setTimeout2
new Promise((res, rej) =>{ console.log(1) res() }).then(() =>{ console.log(2) new Promise((res,rej) =>{ console.log(3) res() }).then(() =>{ console.log(4) }).then(() =>{ console.log(5) }).then(() =>{ console.log(6) }) }).then(() =>{ console.log(7) }) .then(() =>{ console.log(8) }) // 1 2 3 4 7 5 8 6
看完上述內(nèi)容,你們掌握nodejs中怎么循環(huán)瀏覽器事件的方法了嗎?如果還想學到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注億速云行業(yè)資訊頻道,感謝各位的閱讀!
免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。