12. 使用 async & await (Fetch API)

【9.14补充内容】增加了fetch API的应用,然後修改了一些async & await的范例。

async & await


async & await是一个基於promise的语法糖。

运作原理和promise一模一样,主要包含两个部分:

  • 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)) 

执行步骤

  1. fetch() : 会依照参数里指定的url去取得资料,且会直接resolve回传的Promise,这个Promise 会包含 Response物件。
  2. .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】

参考资料:


<<:  【Day03】让我们来看看Sample Code~

>>:  Day 13 - Kotlin的集合(2)

Day 21- To Do List (8) 利用 HTML Template 呈现资料

今天我们一起来实作用 HTML Template 来显示 To-Do-List 的资料吧! 首先我们...

[资料库] 学习笔记 - 商城交易之上架商品

这次练习的题目是做出商城中上架商品的功能 功能主要需求:谁上架了什麽商品、上架数量多少,如果商品没有...

ShadowsocksR/SSR客户端

ShadowsocksR常被称为SSR、酸酸乳、小飞机(粉色)、纸飞机(粉色),是由“破娃酱”发起的...

Day18 - 【概念篇】OAuth flows: PKCE

本系列文之後也会置於个人网站 +-------------------+ | Authz Serv...

[FGL] 程序开发(1) - 基本指令与流程控制

为了协助新进同学,仍应该介绍基本程序的写法 编写小程序验证的做法请参考第一章的套件介绍,hello...