一篇掌握最權威的JS同步異步編程原理(面試必問)

客套話

文章涉及的內容可能不全面,但量不少,須要慢慢看。我花了很長的時間整理,用心分享心得,但願對你們有所幫助。可是不免會有打字的錯誤或理解的錯誤點,但願發現的能夠郵箱告訴我1163675970@qq.com,我會及時的進行修改,只但願對你有所幫助,謝謝。javascript

重要性

接下來呢,咱們把原生js裏有一個很是重要的點 JS同步異步編程 來詳細的看一下 , JS同步異步編程 不只在面試中常常被問到,並且也是咱們在真實的項目開發中,咱們能不能有效的管控咱們的數據請求,管控咱們的異步操做,以及在項目當中咱們不少的業務邏輯中,咱們都得大量的應用同步異步編程的處理,那麼此時須要咱們把同步異步編程可以精準的,進準到骨子裏的去掌握下來java

JS 中的同步和異步編程

JS運行在瀏覽器中(瀏覽器只分配一個線程來運行JS =>JS是單線程的)
JS單線程致使大部分任務都是同步任務,只有及個別的事情屬於異步的,以下:node

  • 事件綁定
  • 定時器
  • AJAX(AXIOS) / FETCH(天生就是異步的)
  • Promise中的同步異步

Promise中的同步異步

  1. new Promise的時候,傳遞的exector函數必定是當即執行的,它屬於同步的
  2. 基於then 或者 catch 存放的方法執行是異步的
new Promise((resolve, reject) => {
        console.1og(1);
        resolve(); //=> resolve()執行纔會進入.then 
}). then(() => {
        console .1og(2);
});
console.1og(3);

<!--輸出 1 3 2 分析: 當new Promise的時候 (resolve, reject) => { console.1og(1); resolve(); //=> resolve()執行纔會進入.then } 1.exector函數是當即執行的 2.當執行完exector後,雖然是執行了resolve(); 可是不會立馬把.then 中的方法當即執行,而是new Promise的 exector執行完以後,先執行then,經過 then 把 它裏面寫的這個方法函數 () => { console .1og(2); } 存起來 ,何時這些函數該執行呢 3.等到主線程的 console.1og(3); 執行完之後,主線程的任務都結束了,纔會去把 resolve();這個執行控制 () => { console .1og(2); } 它執行; --> 複製代碼
  1. async / await 也是異步的,尤爲是await
await 是同步仍是異步? 
    異步,雖然把它理解爲等待同步狀態,但他必定是異步的
async function fn( ) {
    await 10;
    console.1og(1);
}    
fn();
console.1og(2);
<!--輸出 2 1 分析: 若是是同步的,咱們先執行的fn(); 而後進入先等 await 10; 他沒有出來以前,後面的不會執行, 若是是同步的 包括 console.1og(2); 也不會執行 , 可是進入fu 後它裏面的沒有執行就執行 console.1og(2);先輸出了 說明 await必定是異步的 --> 複製代碼
  1. generator 函數
<!--
    在 generator 中執行一個方法,它面的代碼不會執行,
    當咱們只有經過 gt.next();後,代碼纔會一步一步執行,也能夠理解爲異步,
    asyncawait 就是基於generator構建出來的
    ----------------------------------------------------
    建立一個generator函數 名字用*標識的名字,
    都屬於generator生成器函數
-->
function* fn() {
    yield 10;
    console.1og(1);
    yield 20;
    console.1og(2);
}
let gt = fn(); // 在 generator 中,執行fn方法,返回一個對象,它裏面的代碼不會執行
console.log(gt);
gt.next(); // 只有經過next才能控制代碼一點一點的往下走
gt.next();
gt.next();
console.1og(3);

<!--輸出 object [Generator] {} 1 2 3 當只有一個 gt.next();時 只會輸出 一個 3 --> 複製代碼

JS誰如何構建出異步編程的效果?

  • Event Loop 基於 "事件循環機制" (Event Queue 事件隊列)
setTimeout(() => {
    console .1og(1);
},50);
setTimeout(() => {
    console.1og(2);
}, 0); //=>不是當即執行,有一個最小的反映時間
console. time('FOR');I
for(leti=0;i<100000;i++){}
console. timeEnd('FOR'); //=> 循環時間<=10MS
setTimeout(() => {
    console.1og(3);
}, 20);
console.1og(4);
<!--輸出 FOR:3.5ms 4 2 3 1 --> 複製代碼
  • Event Queue 事件隊列中存在兩個任務隊列:面試

    • macro task queue 宏任務隊列 (定時器、事件綁定、AJAX ... )編程

    • micro task queue 微任務隊列 (Promise、async/await ...)promise

  • 只要主棧執行完,到Event Queue中去找要執行的任務瀏覽器

    • 執行順序永遠都是先找微任務,微任務沒有了 ,再找宏任務
    • sync同步 -> micro微任務 -> macro宏任務

講了這麼多,檢測一下吧

這是一個最具經典的面試題 字節跳動 今日頭條異步

是否是題都沒看明白 哈哈哈
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');

<!--輸出 給了答案也不知道是個啥鬼 控制檯輸出: VM90:9 script start VM90:2 async1 start VM90:7 async2 VM90:15 promise1 VM90:20 script end VM90:4 async1 end VM90:18 promise2 VM90:11 setTimeout node下運行 script start async1 start async2 promise1 script end promise2 async1 end setTimeout --> 複製代碼

相關文章
相關標籤/搜索