javascript非同步操作(async, await)

練習

直接執行有setTimeout的Promise, 但因javascript是非同步執行, 不會等待後再執行結束的log
console.log(getTime()+'..start');
new Promise(resolve => {setTimeout(resolve, 1000);  });
console.log(getTime()+'..end');

//結果: 沒有等待
/*
"7:15:28..start"
"7:15:28..end"
*/
修改成async IIFE, 以新增await運算子
(async () => {
	console.log(getTime()+'..start');
	await new Promise(resolve => {setTimeout(resolve, 1000);  });
	console.log(getTime()+'..end');
})();

//結果: first等待1秒鐘
/*
"7:16:59..start"
"7:17:00..end"
*/
目標-執行程式結束後, 再執行另一段-把函式當參數傳入
var start = function(callback) {
	console.log('start '+getTime());
    setTimeout(()=>{
      if( typeof callback === 'function' ){
      	callback();
    	}
    }, 1000); 
}

var next = function() {
    console.log('doNext '+getTime());
}

start(next);

//結果:
/*
"start 21:24:15"
"doNext 21:24:16"
*/

以上程式, 一層一層加疊, 造成callback hell, 會多層巢狀, 很難控制每種狀況及導出的結果

目標-執行程式結束後, 再執行另一段-用async, await控制
//調整start
var start = async() => {
  console.log('start '+getTime());
  await new Promise(resolve => {setTimeout(resolve, 1000);  });
}


(async()=>{
	await start()
	  .then(()=>next());	
})();
目標-先執行一段程式, 並依程式結果, 決定接下來要執行哪段程式
var doNext = () => {
    console.log('doNext '+getTime());
}

var check = async(condition) => {
  console.log(`check ${condition} ${getTime()}..start`);
  await new Promise((resolve, reject) => 	{
    if (condition)	{//依condition決定要走resolve或reject
      setTimeout(function () {resolve();}, 3000);
    } else {
      reject(`failed, rejected.`)
    }
  });
}

/*寫法一: 先then再catch*/
/*
(async () => {
  await check(false)
  .then(()=>doNext())
  .catch(response => {console.log(response);	});
  
  await check(true)
  .then(()=>doNext())
  .catch(response => {console.log(response);	});
})(); 
*/

/*寫法二: then裡直接兩個anonymouse function, 第二個處理catch*/
/*
(async () => {
  await check(false)
  .then(
  	() => doNext(),
    (response) => {console.log(response);}
   );
  
  await check(true)
  .then(
  	()=>doNext(),
    (response) => {console.log(response);}
  );
})(); 
*/

/*寫法三: Promise chain*/
(async () => {
  await check(false)
  .then(
  		(response) => check(true),
    	(response) => {console.log(response);}
   )
   .then(
  		(response) => check(true),
    	(response) => {console.log(response);}
  )
  .then(
  		()=>doNext(),
  );
})(); 
 
//結果
/*
"check false 22:36:36..start"
"failed, rejected."
"check true 22:36:36..start"
"doNext 22:36:39"
*/
以asp.net的async例子-做早餐做練習, 有倒咖啡, 煎蛋, 煎培根, 烤土司並塗上奶油及果醬, 倒果汁共5項工作

目標:一步接一步作業, 做完一項工作, 再開始另一項

var makeBreakfastSteply = async() => {

...
  console.log(`Let's Making Breakfast!`);
  await pourCoffee(2);
  console.log(`coffee is ready`);
  
  await fryBaconAsync(1);
  await fryEggsAsync(4);
  await makeToastWithButterAndJamAsync(2);
  pourJuice();
...
}
//花費約18秒鐘

目標-先倒完咖啡, 再請家人幫忙, 煎蛋, 煎培根, 烤土司並塗上奶油及果醬三項工作同時開工, 待工作都完成, 再倒一杯果汁

var makeBreakfastAsync = async() => {
  console.log(`Let's Making Breakfast!`);
  await pourCoffee(2);
  console.log(`coffee is ready`);
 
  await Promise.all([fryBaconAsync(1), fryEggsAsync(4), makeToastWithButterAndJamAsync(2)])
   .then(() => pourJuice())
   .catch(response => {console.log(response);	});
...
}

//花費約8秒鐘

做早餐完整程式:         https://jsfiddle.net/ripsea/459m6d8v/170/