Javascript 近幾年來受歡迎的原因,有一大部分是因為 JS 可以處理非同步(異步)的問題,也因為可以非同步,所以處理速度快,且可帶給瀏覽者更好的體驗,所以了解如何控制非同步也成了前端重要的技能之一。
無非同步的程式
1 2 3 4 5 6 7 8
   | function add(n1, n2) {   return n1 + n2; } function testNoAsync() {   let result = add(3, 4);   console.log(result); }
 
  | 
 
問題的起源,非同步程式
寫程式如果遇到要處理非同步的程式,就會變得複雜了起來,為什麼會複雜?
預設想要延遲執行,卻出現 undefined 程式會一直往下跑, return 的部分不會回傳會被忽略….。
1 2 3 4 5 6 7 8 9 10 11 12 13
   | function delayedAdd0(n1, n2, delayTime) {      window.setTimeout(function() {     console.log(2);     return n1 + n2;   }, delayTime);   console.log(1);  } function test() {   let result = delayedAdd0(4, 2, 2000);   console.log(result); } test(); 
  | 
 
第一個解決方式 : callback 回呼函式
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | function delayedAdd1(n1, n2, delayTime, callback) {         window.setTimeout(function() {          callback(n1 + n2);   }, delayTime); }
  function test1() {   delayedAdd1(4, 2, 2000, function(result) {     console.log(result);   }); } test1(); 
  | 
 
第二個解決方式 : Promise 物件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
   | function delayedAdd2(n1, n2, delayTime) {      let p = new Promise(function(resolve, reject) {               window.setTimeout(function() {       resolve(n1 + n2);      }, delayTime);   });      return p;  }
  function test2() {   let promise = delayedAdd2(4, 2, 2000);   promise     .then(function(result) {       console.log(result);     })     .catch(function(error) {       console.log('Error', error);     }); }
  | 
 
需求: 需要運行兩次的 promise 然後將結果相乘
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | function test2a() {   let promise1 = delayedAdd2(4, 2, 2000);   let promise2 = delayedAdd2(1, 5, 2000);         Promise.all([promise1, promise2]).then(function(results) {          let answer = results.reduce(function(total, value) {       return total * value;     });     console.log(answer);   }); } test2a();
  | 
 
第三個解決方式 : 使用 Async/Await 簡化 Promise 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
   | 
  function delayedAdd3(n1, n2, delayTime) {      return new Promise(function(resolve, reject) {               window.setTimeout(function() {       resolve(n1 + n2);      }, delayTime);   }); }
  async function test3() {      let result = await delayedAdd2(4, 2, 2000);   console.log(result); }
 
  | 
 
需求 需要運行兩次的 promise 然後將結果相乘
1 2 3 4 5 6 7 8
   | async function test3a() {      let result1 = await delayedAdd2(4, 2, 2000);   let result2 = await delayedAdd2(3, 1, 3000);   let answer = result1 * result2;   console.log(answer); } test3a();
  | 
 
參考 1 彭彭的課程
參考 2 code