Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JS如何運行非同步任務的? #28

Open
BensonLiao opened this issue Jan 14, 2022 · 0 comments
Open

JS如何運行非同步任務的? #28

BensonLiao opened this issue Jan 14, 2022 · 0 comments
Labels

Comments

@BensonLiao
Copy link
Owner

BensonLiao commented Jan 14, 2022

這概念老實說一直困擾著我,
很難真正理解跟內化,
尤其是前幾年ES6開始出現promise這樣的機制,
又把非同步任務調派提高到另一層級的理解複雜度XD
原本以為自己終於能摸熟運作機制,
像是下面的例子:

  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');
  });

以最新的Chrome 97.0.4692.71為環境下會印出下面的結果(FF 96.0跟Edge 97.0.1072.62是一樣的):

script start
async1 start
async2
promise1
async1 end
promise2
setTimeout

以下分析建構執行上下文的過程

  async function async1() {
    console.log('async1 start');
    await async2();
    console.log('async1 end');
  }
  // 放進micro task queue等待執行

  async function async2() {
    console.log('async2');
  }
  // 放進micro task queue等待執行

  console.log('script start');
  // 發現同步任務執行的代碼以此這段先印出

  setTimeout(function () {
    console.log('setTimeout');
  }, 0);
  // 放進macro task queue等待執行

  async1();
  // 執行micro task queue
  // console.log('async1 start'); 這段接著印出
  // await async2(); 發現await關鍵字讓出執行緒處理async2()並暫停執行後面的代碼
  // console.log('async2'); 這段接著印出並將執行緒還回去

  new Promise(function (resolve) {
    console.log('promise1');
    resolve();
  }).then(function () {
    console.log('promise2');
  });
  // 接續console.log('async2');的執行結果
  // 首先創建Promise發現建構式存在
  // 於是接著印出console.log('promise1')
  // 將then後面的函數放進macro task queue等待執行
  // 此時micro task queue的內容:[console.log('async1 end'), console.log('promise2')]
  // 以及macro task queue的內容:[console.log('setTimeout')]
  // 沒有其他同步任務了開始清空queue
  // 按照micro-> macro的順序
  // console.log('async1 end') -> console.log('promise2') -> console.log('setTimeout')

直到看到下面的腦袋爆炸範例:

async function t1 () {
  console.log(1)
  console.log(2)
  await new Promise(resolve => {
    setTimeout(() => {
      console.log('t1p')
      resolve()
    }, 1000)
  })
  await console.log(3)
  console.log(4)
}

async function t2() {
  console.log(5)
  console.log(6)
  await Promise.resolve().then(() => console.log('t2p'))
  console.log(7)
  console.log(8)
}

t1()
t2()

你可以正確地答出log順序嗎?
這概念真的滿不好用文字解釋的待補充

參考資料:
关于 Await、Promise 执行顺序差异问题
8张图帮你一步步看清 async/await 和 promise 的执行顺序
JS task到底是怎么运行的

@BensonLiao BensonLiao added the TIL label Jan 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant