js有三個大問題:做用域,原型鏈,同異步node
同異步想要知道同異步問題就要找到js的運行機制:ajax
js是單線程:同一時間只能執行一件事情編程
瀏覽器是多線程:同一時間內能執行多件事情promise
爲何js是單線程:假若有2個函數同時執行,一個是添加元素,一個是刪除元素,瀏覽器就不知道該如何執行,因此js設計成了單線程瀏覽器
例如在瀏覽器中打開一個HTML頁面的時候,就佔用了一個進程,瀏覽器分配一個線程去計算DOM樹,分配其餘線程去加載對應的資源文件,再分配一個線程去自上而下執行js多線程
能夠查看瀏覽器控制檯的Network,有不少線程在進行異步
同步:在一個線程上(主棧 / 主任務隊列)同一個時間只能作一件事情,當前事情完成才能進行下一個事情(先把一個任務進棧執行,執行完成,再進行下一個進棧,上一個任務出棧)async
異步:在主棧中執行一個任務,發現這個任務是異步的操做,會把異步操做移出主棧,放到等待任務隊列中,這個時候瀏覽器會再分配其餘線程監聽異步任務是否到達指定的執行時間,等待主棧執行完,監聽者會把到達時間的異步任務,從新放到主棧中執行異步編程
在js中,分爲執行隊列和等待隊列,當遇到異步任務,會把該任務對應的回調函數放到等待隊列中,當執行隊列中執行完畢,再去等待列隊查看知足條件的任務,把其對應的回調放到主任務隊列中執行,主任務隊列也叫執行棧函數
所謂js中的異步編程僅僅是根據某些機制來管控任務的執行順序,不存在同時執行兩個任務一說
在js中異步執行的有:setTimeout / set 、ajax 、事件綁定,回調函數,Promise(async / await)、node的process.nextTick、node的fs的I/O操做
setTimeOut(()=>{ console.log(1);//再輸出1 },10) for(let i=0; i<1000; i++){//同步 } console.log(100); //先輸出100
let xhr = new XMLHttpRequest();//第一步進棧new一個實例後再出棧 xhr.open('GET','XXX.JSON',false);//第二步進棧 執行open後再出棧,設置爲同步 此時 readyState=1 xhr.onreadystatechange=function(){//此時進棧發現監聽事件是異步,放等待任務中,此時 readyState=1;第四步當執行完send,readyState=4的時候 執行異步 console.log(xhr.readyState);//readyState=4 } xhr.send();//第三步執行 同步任務send ,此時readyState=4的時候主棧空閒
ajax開始是send開始,結束是狀態爲4結束
let xhr = new XMLHttpRequest();//第一步進棧new一個實例後再出棧 xhr.open('GET','XXX.JSON',false);//第二步進棧 執行open後再出棧,設置爲同步 此時 readyState=1 xhr.send();//第三步執行 同步任務send ,此時readyState=4,結束 xhr.onreadystatechange=function(){//狀態改變的時候纔會觸發監聽,放等待隊列的時候狀態已是4了,不會再改變了,因此不會執行這個方法了 console.log(xhr.readyState);//一次都不輸出 }
let xhr = new XMLHttpRequest();//第一步進棧new一個實例後再出棧 xhr.open('GET','XXX.JSON',true);//第二步進棧 執行open後再出棧,設置爲異步 此時 readyState=1 xhr.send();//第三步執行 同步任務send ,會有一個線程是去請求數據,主棧空閒下來,此時readyState=1, //發現異步,放等待隊列中,此時readyState=1 xhr.onreadystatechange=function(){//主棧空閒了,readyState變成2,函數執行一次, //狀態爲3的時候,又執行一次, //狀態爲4的時候,把函數又執行一次 console.log(xhr.readyState); //2,3,4 }
js事件:主線程不斷的重複得到消息,執行消息,再取消息,再執行...事件循環
宏任務和微任務
主線程每次只能執行一個任務,當主線程執行完畢,會首先去微任務隊列中去獲取第一個執行任務,當把微任務中的任務隊列中的任務執行完成,纔去宏任務隊列去尋找該執行的任務
宏任務:定時器,ajax,setImmendiate
微任務:promise的then,async await , process.nextTick
若是遇到了多個微任務,誰先放入誰先執行,微任務執行完畢,再去執行宏任務