1、前言瞭解
js本是單線程,但很多時候,單線程效率太慢,影響進度,於是又有了多進程的發展,當然這僅僅是在單線程裏站隊將其分解多步解決問題。
2、同步異步的瞭解
- 同步是指按照順序執行的操作,當前一件事未完成之前,後面的事件都不能啓動。
- 異步則不一樣,異步就是指多件事情可以同時操作,不需要誰等誰。
- 同步就像是隻有一個隊列,該隊列只有一個窗口可以解決問題,而異步就像是一個隊列,但是隊列中的每一項都有一個窗口可以解決問題。
同步異步區別
3、微觀、宏觀
- 這裏只需要知道微觀事件有哪些,微觀事件是歸類到微觀隊列裏去的,主要有Promise.then的回掉函數
- 宏觀事件比較多,比如定時器、script塊、IO設備等等
4、任務隊列
- 事件執行的時候遇到異步操作就會提交給瀏覽器的API,而webAPI就會將其註冊列表內,然後再根據優先級(各個瀏覽器優先級不一樣)返回到任務隊列裏面,任務隊列將其分成微觀隊列和宏觀隊列,對應的就是微觀事件和宏觀事件。
5、事件循環
1)js在執行棧裏執行事件
2)先在執行棧裏面執行事件,遇到異步操作就將其返回給WebApl,WebApi再返回隊列。
3)執行棧裏的事件執行完畢後,先到該隊列裏找到是否有微觀事件,有就執行
4)微觀事件執行完畢,查看隊列裏是否有宏觀任務,再執行按照步驟1234即可
5)這樣不斷的執行尋找就是事件循環
6、代碼實現
1)首先上一個簡單的例子
<script type="text/javascript">
new Promise(function(resolve){
console.log(1)
for( var i=0 ; i<10000 ; i++ ){
i==9999 && resolve()
}
console.log(2)
}).then(function(){//promise的回掉函數
console.log(5)
});
setTimeout(function(){console.log(4)},0);
console.log(3);
</script>
上面代碼執行順序是怎樣的呢,下面可以根據事件循環的機制走一遍
1)js在執行棧裏執行事件(script就是第一個宏觀任務,也就是執行棧)
2)先在執行棧裏面執行事件,首先是promise的函數是一個普通函數,故執行裏面代碼,可得到結果1、2,然後遇到了.then回掉函數將其返回給WebApl,WebApi再返回到微觀隊列。再往下執行遇到了setTimeout定時器,是宏觀任務就將其返回到宏觀隊列的任務列表,之後再執行最後一步得到3
3)執行棧裏的事件執行完畢後,先到該隊列裏找到是否有微觀事件,咱們的微觀任務隊列裏面有.then回掉函數,故可以先執行這個操作得到結果5
4)微觀事件執行完畢,再到隊列裏查看是否有宏觀事件,這時發現了定時器故執行後的結果4
5)不斷的查看隊列,直到隊列爲空即可
最後可以輸出結果答案就是12354
按照以上步驟大家可以檢測一下自己是否真正懂了,以下是一份稍微複雜的執行代碼。
console.log('1');
setTimeout(function() {
console.log('2');
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
大家可以按照上面寫的js的執行順序去執行看自己是否真正理解掌握了
最後結果是1、7、8、2、4、5、9、11、12。
7、總結
不管是怎麼複雜的事件,只要記住,先執行看到的,遇到異步操作先不管,先走執行棧裏面的代碼,執行完畢後再微觀隊列然後宏觀隊列。