簡單聊聊JavaScript的事件循環(huán)機(jī)制
前言
JavaScript是一門單線程的弱類型語言,但是我們在開發(fā)中,經(jīng)常會(huì)遇到一些需要異步或者等待的處理操作。
類似ajax,亦或者ES6中新增的promise操作用于處理一些回調(diào)函數(shù)等。
概念
在JavaScript代碼執(zhí)行過程中,可以分為同步隊(duì)列和異步隊(duì)列。
同步任務(wù)類似我們常說的立即執(zhí)行函數(shù),不需要等待可以直接進(jìn)行,可以直接進(jìn)入到主線程中去執(zhí)行,類似正常的函數(shù)調(diào)用等。
異步隊(duì)列則是異步執(zhí)行函數(shù),類似ajax請求,我們在發(fā)起的過程中,會(huì)進(jìn)入到一個(gè)異步隊(duì)列,加載到任務(wù)當(dāng)中時(shí),需要進(jìn)行等待,之后才能進(jìn)行返回值的處理。
舉個(gè)栗子
下面一段代碼,我們可以先了解一些一些關(guān)于事件循環(huán)機(jī)制的一些基本的原理
console.log('1'); setTimeout(function() { console.log('4'); }, 0); Promise.resolve().then(function() { console.log('2'); }).then(function() { console.log('3'); }); console.log('5');
我們將代碼打印到控制臺當(dāng)中,輸出結(jié)果是:1,5,2,3,4
我們知道,在JavaScript中,類似定時(shí)器,以及ES6新增的promise是異步函數(shù),回到我們上面所說的隊(duì)列的概念當(dāng)中,不難得出,1和5為同步執(zhí)行隊(duì)列
在執(zhí)行完同步隊(duì)列中的代碼之后,再執(zhí)行異步隊(duì)列中的代碼。
TIP
在解析異步隊(duì)列的promise和定時(shí)器中,我們發(fā)現(xiàn),定時(shí)器setTimeout是后執(zhí)行于promise,這里我們引入JavaScript規(guī)范中的宏任務(wù)(Macro Task)和微任務(wù)(Micro Task)的概念
在JavaScript中,宏任務(wù)包含了:script( 整體代碼)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 環(huán)境)
微任務(wù):Promise、MutaionObserver、process.nextTick(Node.js 環(huán)境)
再回到上面的定時(shí)器和promise的問題,這時(shí)候我們知道,JavaScript中,當(dāng)有異步隊(duì)列的時(shí)候,優(yōu)先執(zhí)行微任務(wù),再執(zhí)行宏任務(wù)
再次舉個(gè)栗子
假如在異步隊(duì)列當(dāng)中存在異步隊(duì)列時(shí),我們需要怎么處理
console.log(1); setTimeout(function() { console.log(5); }, 10); new Promise(resolve => { console.log(2); resolve(); setTimeout(() => console.log(3), 10); }).then(function() { console.log(4); }) console.log(6);
將代碼執(zhí)行到控制臺中,得出的打印順序是:1,2,6,4,5,3
- 不同于例子1當(dāng)中的promise,打印2是優(yōu)先于6執(zhí)行的,由此我們可以知道,new Promise在執(zhí)行過程中,在未執(zhí)行resolve或者rejected前,所執(zhí)行的代碼均為同步隊(duì)列中的代碼。
- 再看4,5,3的執(zhí)行順序,在執(zhí)行微任務(wù)promise執(zhí)行回調(diào)resolve之后,對應(yīng)的then立即執(zhí)行
- 在打印結(jié)果中,定時(shí)器5優(yōu)先執(zhí)行于—->屬于微任務(wù)promise中的宏任務(wù)定時(shí)器3,定時(shí)器5這個(gè)宏任務(wù)是在promise微任務(wù)這個(gè)隊(duì)列之后就加進(jìn)去,在promise執(zhí)行完成then回調(diào)之后,promise中的宏任務(wù)才加入到隊(duì)列當(dāng)中,因此在定時(shí)器5之后執(zhí)行
總結(jié)
在JavaScript中,宏任務(wù)包含了:script( 整體代碼)、setTimeout、setInterval、I/O、UI 交互事件、setImmediate(Node.js 環(huán)境)
微任務(wù):Promise、MutaionObserver、process.nextTick(Node.js 環(huán)境);
在執(zhí)行過程中,同步代碼優(yōu)先于其他任務(wù)隊(duì)列中的代碼,
定時(shí)器,promise這類任務(wù),在執(zhí)行過程中,會(huì)先加入隊(duì)列,
在執(zhí)行完同步代碼之后,再根據(jù)宏任務(wù)和微任務(wù)的分類,先執(zhí)行微任務(wù)隊(duì)列,再執(zhí)行宏任務(wù)隊(duì)列。
到此這篇關(guān)于JavaScript事件循環(huán)機(jī)制的文章就介紹到這了,更多相關(guān)JS事件循環(huán)機(jī)制內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
js form表單input框限制20個(gè)字符,10個(gè)漢字代碼實(shí)例
這篇文章主要介紹了js form表單input框限制20個(gè)字符,10個(gè)漢字,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04一文快速弄懂webpack動(dòng)態(tài)import原理
無論你開發(fā)使用的是CommonJS規(guī)范還是ES6模塊規(guī)范,打包后的文件都統(tǒng)一使用webpack自定義的模塊規(guī)范來管理、加載模塊,下面這篇文章主要給大家介紹了關(guān)于webpack動(dòng)態(tài)import原理的相關(guān)資料,需要的朋友可以參考下2022-04-04JavaScript中的普通函數(shù)和箭頭函數(shù)的區(qū)別和用法詳解
這篇文章主要介紹了JavaScript中的普通函數(shù)和箭頭函數(shù)的區(qū)別和用法詳解,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-03-03vue2.0實(shí)戰(zhàn)之基礎(chǔ)入門(1)
這篇文章主要為大家詳細(xì)介紹了vue2.0實(shí)戰(zhàn)第一篇基礎(chǔ)入門的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03js加載之使用DOM方法動(dòng)態(tài)加載Javascript文件
傳統(tǒng)上,加載Javascript文件都是使用script標(biāo)簽,我們也可以使用DOM方法,動(dòng)態(tài)加載Javascript文件,具體實(shí)現(xiàn)如下,感興趣的朋友可以參考下2013-11-11表格展示利器 Bootstrap Table實(shí)例代碼
在表格導(dǎo)出數(shù)據(jù)中,發(fā)現(xiàn)設(shè)置了分頁參數(shù),導(dǎo)出的數(shù)據(jù)僅為表格加載的分頁參數(shù)數(shù)據(jù),于是,針對這樣的情況,通過設(shè)置分頁參數(shù)的值,使表格可以加載更多的數(shù)據(jù),可達(dá)到導(dǎo)出所有數(shù)據(jù)的功能需求。下面通過本文給大家分享表格展示利器 Bootstrap Table2017-09-09js時(shí)鐘翻牌效果實(shí)現(xiàn)代碼分享
這篇文章主要介紹了javascript時(shí)鐘翻牌效果的實(shí)現(xiàn),效果非常酷炫,實(shí)現(xiàn)步驟也很簡單,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2015-08-08JS如何獲取指定范圍內(nèi)的隨機(jī)數(shù)含小數(shù)
這篇文章主要介紹了JS如何獲取指定范圍內(nèi)的隨機(jī)數(shù)含小數(shù)問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12