關於js的同步和非同步,個人理解
阿新 • • 發佈:2018-11-10
之前對JS的同步和非同步一直搞不清楚,今天看了些文章,談談自己的理解。
非同步函式往往是有等待性質的函式,主流程在執行到等待的時候,為了提高效率,就把這個函式掛起了,放進一個等待的佇列。接著主程式繼續執行後面的函式。
一直執行到主程式佇列裡的函式執行完畢,這時主程式再去查詢等待佇列裡哪個程式等待結束。這個查詢發生的條件是主程式裡的函式都執行結束。如果等待佇列裡有已經結束等待的函式,主程式就把它拿到主程式佇列裡執行並返回結果。
就像一個坐診醫生,病人A,B,C,D依次來看病。
A進入診室,B,C,D在後面排隊等待。
A的病很簡單,醫生檢查開藥,診斷結束。
A離開診室,B進入診室,C,D在後面排隊。
B的病情複雜,醫生說你去查個血,等我看完後面的病人再來找你。
B離開診室,C進入診室看病,D在後面排隊;
C看完後,離開診室,D進入診室。*不論此時B是否已經查血完成
D看完後離開。如果沒有新的病人來,這時醫生每隔一段時間檢視B的查血報告是否完成。
如果發現B的查血報告,就叫B進入診室,繼續診斷開藥,診斷結束。
值得注意的是,B有個簡單的初診(執行到掛起階段),在B離開後(進入等待佇列),哪怕B的查血報告很快出來,也需要等到D結束診斷後才能繼續進行診斷。
用程式模擬如下:
(function f() { console.log('開始看病'); console.log('A看病結束'); setTimeout(()=>console.log('B看病結束'),0); console.log('C看病結束'); console.log('D看病結束'); })();
執行結果為:
可見B只用了0毫秒去查血,仍要等所有人都結束後才能繼續看病
之前很疑惑非同步函式是否不做任何處理直接放到掛起等待的佇列,等所有程式都結束才開始執行非同步函式。
用以下程式驗證發現,非同步函式在進入等待掛起前開始倒計時,只是倒計時結束不會返回結果。
結果中會先輸出'end function!',然後很快依次輸出1,2,等待大約1秒輸出3(function f() { console.log('begin function.'); setTimeout(()=>console.log(1),1000); setTimeout(()=>console.log(2),2000); setTimeout(()=>console.log(3),6000); var start_t=new Date().getTime(); while(new Date().getTime()-start_t<5000){} console.log('end function!'); })();