備忘錄_20160105(定位) 修改 回首頁

程式 2020-05-21 04:52:04 1590007924 100
JavaScript Promise, async, await

JavaScript Promise, async, await

<script>

function waitForMe()
{
  return new Promise
  (
    (成功, 失敗) => 
    {
      // 標的:成功、失敗、throw
      
      // 任何時候,只要一遇到 「throw」,後面的程式就不會再執行。
      //       若遇到「throw」之前,沒有呼叫過「成功」或「失敗」函數,
      //       則跳到 catch
      
      // 只要遇到第一個「成功」或「失敗」函數呼叫,
      // 後頭不管還有多少個「成功」或「失敗」呼叫,一概不予理會。
      // 但請注意,「成功」或「失敗」函數呼叫之後的程式碼,"還會"繼續執行喔!
      
      // 因為上述兩條規則,在錯縱複雜的執行情形底下,
      // 有可能最後執行到 then ,但其實是有錯誤發生的,而且看不到!!!  (例如 condition=1)
      // 或是有 throw 發生,但你可能只會看到「失敗」函數呼叫的結果!!! (例如 condition=2)
      // 或是有「成功」函數+「失敗」函數+throw,但您只會看到成功訊息!   (例如 condition=3)
      
      var condition=3;
      
      console.log("Promise created.(檢查點 A)");
      
      if((condition & 1)==1)
      {
        console.log("Promise created.(檢查點 B)");
        成功('成功函數的呼叫,僅第一個有用');
        成功('成功函數的呼叫,第二個(含)之後都會被忽略');
      }
      
      if((condition & 2)==2)
      {
        console.log("Promise created.(檢查點 C)");
        失敗('失敗函數的呼叫,僅第一個有用');
        失敗('失敗函數的呼叫,第二個(含)之後都會被忽略');
      }
      
      console.log("Promise created.(檢查點 D)");
      throw 'throw 錯誤!throw 錯誤!';
      
      console.log("Promise created.(檢查點 E)");
    }
  )
  .then(  (參數)=>{ console.log("最後結果 success:"+參數); } )
  .catch( (參數)=>{ console.log("最後結果 failure:"+參數); } );

}

async function main()
{
  console.log("main() begin...");
  await waitForMe();
  console.log("main() end...");
}

console.log("before main() ......");
main();
console.log("after main() ...... 照樣非同步執行喔!");

// 04:21:58.841 before main() ...... a.htm:60:9
// 04:21:58.842 main() begin... a.htm:55:11
// 04:21:58.843 Promise created.(檢查點 A) a.htm:26:15
// 04:21:58.844 Promise created.(檢查點 B) a.htm:30:17
// 04:21:58.844 Promise created.(檢查點 C) a.htm:37:17
// 04:21:58.845 Promise created.(檢查點 D) a.htm:42:15
// 04:21:58.845 after main() ...... 照樣非同步執行喔! a.htm:62:9
// 04:21:58.846 最後結果 success:成功函數的呼叫,僅第一個有用 a.htm:48:27
// 04:21:58.846 main() end... a.htm:57:11

</script>

<script>

function delay(interval)
{
  // usage:
  //
  //   async function main()
  //   {
  //     ......
  //     await delay(3000);
  //     ......
  //   }
  //   
  //   main();
  //
  
  return new Promise((empty)=>{ setTimeout(empty, interval); });
}

function complexDelay(taskName, interval)
{
  return new Promise
  (
    (成功)=>
    {
      console.log(taskName+" 工作開始,需時 "+(interval/1000)+" 秒");
      window.setTimeout(()=>{ 成功(taskName); }, interval); 
    }
  )
  .then( (value)=>{ console.log("("+value+"-"+interval+") - 完成!"); } );
}

async function task(taskName, interval1, interval2)
{
  console.log(taskName+" 工作開始");
  await complexDelay(taskName+"第一階段", interval1);
  await complexDelay(taskName+"第二階段", interval2);
  console.log(taskName+" 工作結束");
}

async function main()
{
  await task("晨間開會", 3000, 2000);
  await task("撰寫程式", 1000, 4000);
}

console.log("before main() -- 非同步喔");
main();
console.log("after main() -- 非同步喔");

// 04:51:28.576 before main() -- 非同步喔 b.htm:47:9
// 04:51:28.577 晨間開會 工作開始 b.htm:35:11
// 04:51:28.577 晨間開會第一階段 工作開始,需時 3 秒 b.htm:26:15
// 04:51:28.578 after main() -- 非同步喔 b.htm:49:9
// 04:51:31.578 (晨間開會第一階段-3000) - 完成! b.htm:30:29
// 04:51:31.579 晨間開會第二階段 工作開始,需時 2 秒 b.htm:26:15
// 04:51:33.580 (晨間開會第二階段-2000) - 完成! b.htm:30:29
// 04:51:33.581 晨間開會 工作結束 b.htm:38:11
// 04:51:33.581 撰寫程式 工作開始 b.htm:35:11
// 04:51:33.582 撰寫程式第一階段 工作開始,需時 1 秒 b.htm:26:15
// 04:51:34.583 (撰寫程式第一階段-1000) - 完成! b.htm:30:29
// 04:51:34.584 撰寫程式第二階段 工作開始,需時 4 秒 b.htm:26:15
// 04:51:38.584 (撰寫程式第二階段-4000) - 完成! b.htm:30:29
// 04:51:38.585 撰寫程式 工作結束 b.htm:38:11

</script>

其他參考JavaScript 永遠是同步的,單一執行緒的。只是太多地方隱含 callback