async : async function 宣告一個非同步函式,可以告訴function在最後 回傳一個promise await : await必須放在任何基於promise的函數之前, 等到獲得resolve的資料後,再執行後續動作
(await放在async function裡才有作用。)

假設原來的程式碼長這樣:

function greeting() { 
  return new Promise( (resolve,reject) => {
    resolve("Hello"); 
greeting()
  .then((value) => console.log(value));
// output: "Hello"

【async】

我們先嘗試使用async:

async function greeting() { return "Hello" };
greeting()
  .then((value) => console.log(value));
// output: "Hello"

因為非同步函式greeting()回傳的會是一個promise,所以可以省略建構promisenew Promise

【await】

而await必須放在任何基於promise的函數之前,
改寫new Promise建構式的寫法:

async function greeting(){
    let example = await new Promise( (resolve,reject) => {
    resolve("Hello"); 
return example;
greeting()
  .then((value) => console.log(value));
// output: "Hello"

await的作用是,
在得到resolve的物件後,才執行let example的給值。

【Promise.resolve()】

更簡便的寫法,可以使用Promise.resolve()函式:

async function greeting(){
    let example = await Promise.resolve("Hello");
    return example;
greeting()
  .then((value) => console.log(value));
// output: "Hello"

我們可以用Promise.resolve()這個方法回傳一個 指定resolve值的promise,
這裡的重點是 一樣要加上await。

【Promise.reject()】

async function greeting(){
    let example = await Promise.reject("Error"); 
    return example;
greeting()
  .then((value) => console.log(value))
  .catch((error) => console.log(error))
// output: "Error"

我們可以用Promise.reject()這個方法,則回傳一個reject的promise,
一樣可以用catch來獲得錯誤訊息。

【try & catch】

async & await 也可以搭配另一種處理錯誤訊息的方法,也就是 try & catch

繼續改寫上面的例子:

async function greeting(){
  try {
    let example = await Promise.resolve("Hello"); 
    console.log(example);
  } catch (error) {
    console.log(error);
greeting();
// output: "Hello"

try負責正常獲得資料的處理,catch 則能直接獲取錯誤訊息。

好了!學到這裡可以嘗試接外部的API的,
但今天不用XHR(XMLHttpRequest),改用另一種更現代的方式。

Fetch API

API(Application Programming Interface)可以視為一種的工具,用於讓開發者便於請求資料。

Fetch API 提供了 fetch() 方法,fetch() 會回傳一個不論請求成功或失敗,都是 resolve 的 promise。

fetch() 的參數必須為請求資料的網址。

首先可以嘗試使用 Fetch 發送請求 ( request ),這裡我們使用 {JSON} Placeholder 作為例子。
( 可以參考 JSONPlaceholder - Free Fake REST API)

const request = 'https://jsonplaceholder.typicode.com/todos/1';
// fetch 會依照 request 去取得資料
fetch(request)
  .then(response => response.json()) // json()會解析回傳的Response物件
  .then(json => console.log(json)) 
fetch() : 會依照參數裡指定的url去取得資料,且會直接resolve回傳的Promise,這個Promise 會包含 Response物件。
.json() : fetch()回傳的Promise( Body text )還要需要經過解析,.json()是其中一種。
.json()會把fetch回來的Promise解析成JSON型別Promise。

The fetch() method...
It returns a Promise that resolves to the Response to that request — as soon as the server responds with headers — even if the server response is an HTTP error status.

這樣會回傳URL裡todos/裡的第一筆資料。

// output:
	"userId": 1,
	"id": 1,
	"title": "delectus aut autem",
	"completed": false

Everything together!!

那來嘗試把資料改寫成async await吧!
原本的程式碼:

let requestURL = 'https://jsonplaceholder.typicode.com/todos/1';
fetch(requestURL)
    .then((response) => {
        return response.json();
    .then((data) => {
        console.log(`Title: ${data.title}`);
        if (data.completed !== true){
          console.log("Undo");
        } else {
          console.log("Done!!");
    .catch((error) => {
        console.log(`Error: ${error}`);
/* output:
    "Title: delectus aut autem"
    "Undo"

改寫: 使用 async&await,並利用 try&catch 處理錯誤訊息。

let requestURL = 'https://jsonplaceholder.typicode.com/todos/1';
async function getTodoList(url){
  try {
    let response = await fetch(url);
    let data = await response.json();
    console.log(`Title: ${data.title}`);
    if (data.completed !== true){
      console.log("Undo");
    } else {
      console.log("Done!!");
  } catch(error) {
    cconsole.log(`Error: ${error}`);
getTodoList(requestURL);

fetch相較於XHR更強大且更有彈性(意思應該是fetch有很多功能),MDN提供了很多使用方式和範例,可以參考這個頁面: Using Fetch - Web APIs | MDN

一樣放上一些相關的問題:

Promise 和 async await 要解決的是什麼問題?
解決舊語法產生callback hell的問題,避免呼叫太多callback時,程式碼難以判讀且後續難以維護。
(這題其實是考callback hell,詳細可以看舊文章,因為今天才複習async await所以放在這。)

【如內文有誤還請不吝指教>< 謝謝閱覽至此的各位:D】

參考資料:

Fetch API - Web APIs | MDN JavaScript基本功修練:Day28 - Fetch練習(GET和POST請求)
-----正文結束-----