今天要學習的是 Async 與 Await,是為了簡化 Promise 物件的操作流程而誕生。
來看看 MDN 怎麼描述:
async/await 函式的目的在於簡化同步操作 promise 的表現,以及對多個 Promise 物件執行某些操作。就像 Promise 類似於具結構性的回呼函式,同樣地,async/await 好比將 generator 與 promise 組合起來。
原本使用 Promise 物件時,我們會需要透過 then() 與 catch 取得 resolve 與 reject 的結果。 但 async/await 的出現簡化了透過then() 與 catch 取得值的過程
來看一個測試例子:
//定義一組 promise
const runTime = (time, person) => {
  return new Promise((reslove, reject) => {
    setTimeout(() => {
      reslove(`${person}`)
    }, time);
  });
}
// 透過 then() 取得 resolve 的結果
const result = runTime(3000, 'Bill').then(res => console.log(res));
console.log(result);
上述預期可以得到的值為 Bill,應該沒有問題。
再來看看透過 async/await 改寫一下上面的例子:
function runTime(time, person) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`${person}`);
    }, time);
  });
}
async function getPerson() {
    const result = await runTime(3000, 'Bill');
    console.log(result);
  }
getPerson();
在前面有提到,async/await 的出現簡化了透過then() 與 catch 取得值的過程。
所以預期可以得到的值為 Bill。
先記住這個差別,接下來要提提 async/await 為什麼能夠這麼做。
以下是 MDN的語法:
async function name([param[, param[, ... param]]]) {
   statements
}
首先是 async 關鍵字,在函式前寫上 async, 表示該函式為一個非同步函式,並且會得到一個 Promise 物件的回應結果
let sayHi =  async () => 'Hello!';
sayHi() // 預期可以得到一個 Promise {<resolved>: "Hello!"} 的回應
然後我們就可以透過 then() 的方式取得最後結果
let sayHi =  async () => 'Hello!';
sayHi().then(res => console.log(res)) 
再來是 await 關鍵字,當這個函式被呼叫時,透過撰寫在 statements 裡面的 await 接收一個 Promise 物件,並且會等到解析完當前Promise 物件的狀態(resolve 或 reject)後才會繼續往下執行。
let sayHi =  async () => await Promise.resolve('Hello');
sayHi() 
這邊要注意的是 await 會中斷 async 函式的執行直到解析完Promise 物件的狀態後才往下執行。
所以今天如果有多個 非同步函式使用 async/await 的話,秒數則為加總後的時間。
來看看這個測試例子:
function runTime(time, person) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`${person}`);
    }, time);
  });
}
async function getTimes() {
  console.time();
  const result = await runTime(1000, 'Bill');
  const result2 = await runTime(3000, 'Jack');
  console.timeEnd();
}
  
getTimes();
透過設定 console.time() 、 console.timeEnd() 計算使用 async/await 的非同步函式的總執行時間。會發現約4000毫秒(約4秒),因為 async/await是一個執行完成後再執行下一個的(串行執行)。

那問題來了,如果要能並行執行呢?
還記得前一篇提到的 Promise.all 吧?
這裡就要透過 async/await 搭配 Promise.all,來看看測試例子:
function runTime(time, person) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`${person}`);
    }, time);
  });
}
async function getTimes() {
    console.time();
    const result = await Promise.all([runTime(1000, 'Bill'),runTime(3000, 'Jack')]);
    console.timeEnd();
  }
  
getTimes();
從得到的結果可以發現,使用 Promise.all 可以並行執行,進而縮短執行時間。

async/await 搭配 fetch 介接高雄市資料開放平臺的 open data最後以介接 open data的實作結束這一回合~
<!-- css part -->
<style>
  body {
    background: #f0d0d0;
  }
  h1 {
    text-align: center;
    font-weight: bold;
    font-size: 48px;
  }
  .charge-list {
    display: flex;
    list-style: none;
    flex-wrap: wrap;
  }
  .charge-list li {
    box-sizing: border-box;
    flex: 0 1 24%;
    padding: 10px;
    margin: 0 1% 2% 0;
    border-radius: 10px;
    transition: all .4s;
  }
  .charge-list li:hover {
    margin-top: -1%;
  }
  .charge-list li:nth-child(n) {
    background: #aaaadd;
  }
  .charge-list li:nth-child(2n) {
    background: #ddddaa;
  }
  .charge-list li:nth-child(3n) {
    background: #dad;
  }
  .charge-list li:nth-child(3n+1) {
    background: #aaf;
  }
</style>
<!-- html -->
<ul class="charge-list"></ul>
async/await 搭配 fetch 介接open datafetchData = endPoint => fetch(endPoint).then(res => res.json());
(async function getData() 
  const endPoint = 'https://data.kcg.gov.tw/dataset/a98754a3-3446-4c9a-abfc-58dc49f2158c/resource/48d4dfc4-a4b2-44a5-bdec-70f9558cd25d/download/yopendata1070622opendatajson-1070622.json';
  try {
    let chargeStation = await fetchData(endPoint);
    createDomElement(chargeStation);
  } 
  catch(e){
    console.log(e);
  } 
})();
function createDomElement(chargeStation) {
  const domElements = chargeStation.map(place => {
    return `
    <li>
      <p class="location">位置: ${ place.Location }</p>
      <p class="address">地址:${ place.Address }</p>
    </li>
  `;
  }).join("");
  
  const chargeList = document.querySelector('.charge-list');
  chargeList.innerHTML = domElements;
}
今天就先到這裡囉~
明天見~