async function async1() {
console.log("async1 start");
await async2();
console.log("async1 end");
}
async function async2() {
console.log( 'async2');
}
console.log("script start");
setTimeout(function () {
console.log("settimeout");
},0);
async1();
new Promise(function (resolve) {
console.log("promise1");
resolve();
}).then(function () {
console.log("promise2");
});
console.log('script end');
複製代碼
題目的本質,是考察setTimeout
、promise
、async await
的實現順序及JS的時間循環方面的相關問題。javascript
結果爲: script start async1 start async2 promise1 script end async1 end promise2 settimeout
java
這裏涉及到同步異步Microtasks
和Macrotasks
。 Microtasks
優先級別高於Macrotasks
其中Microtasks
、Macrotasks
分別是:promise
所以事件循環的順序,決定了JavaScript代碼的執行順序。它從script(總體代碼)開始第一次循環。以後全局上下文進入函數調用棧。直到調用棧清空(只剩全局),而後執行全部的micro-task。當全部可執行的micro-task執行完畢以後。循環再次從macro-task開始,找到其中一個任務隊列執行完畢,而後再執行全部的micro-task,這樣一直循環下去。瀏覽器
首先,要明確的一點:javascript是以單線程的方式運行的。JavaScript的主要用途是與用戶互動,以及操做DOM。若以多線程的方式,則可能出現衝突。假設有兩個線程同時操做一個DOM元素,線程1要求瀏覽器刪除DOM,而線程2卻要求修改DOM樣式,這時瀏覽器就沒法決定採用哪一個線程的操做。固然,咱們能夠爲瀏覽器引入「鎖」的機制來解決這些衝突,但大大提升複雜性,因此 JavaScript從誕生開始就選擇了單線程執行。在某一時刻內只能執行特定的一個任務,而且會阻塞其它任務執行。 可是JavaScript 有個基於「Event Loop」併發的模型(不是並行)。前者是邏輯上的同時發生,然後者是物理上的同時發生。因此,單核處理器也能實現併發。 上圖說明一下併發和並行:bash
小tips:多線程
console.log(1);
setTimeout(function(){
console.log(2);
Promise.resolve(1).then(function(){
console.log('ok')
})
})
setTimeout(function(){
console.log(3)
})
複製代碼
分析:先默認走棧,輸出1。此時並無微任務,因此微任務不會執行。先走第一個setTimeout,輸出2,同時將微任務放到隊列中,執行微任務,輸出ok,微任務執行完,再走宏任務,輸出3。併發
V8引擎解析JavaScript腳本。 解析後的代碼,調用Node API。 libuv庫負責Node API的執行。它將不一樣的任務分配給不一樣的線程,造成一個Event Loop(事件循環),以異步的方式將任務的執行結果返回給V8引擎。 V8引擎再將結果返回給用戶。異步
淺談event loopasync