Fetch、Promise 介紹與應用


Posted by Christy on 2021-09-16

本篇是 MTR05 W13「Fetch 與 Promise 補充系列」的筆記

Fetch 與 Promise 補充系列(一):初探 Fetch

前言:胡立說這個不太好解釋,如果不懂,一直用就知道在幹嘛了;Mocky:可以自己做一個 api

1. fetch 的 GET 怎麼用?

fetch('https://run.mocky.io/v3/2f3916bb-9322-4e0c-bdd8-29d62933be4e')

1.1 fetch 以後會回傳一個 promise,是一個物件

1.2 要對 promise 拿資料的話,就要用 .then()

1.3 .then() 回傳的東西還是一個 promise

2. 用 fetch 抓 api,要拿到 response 這樣寫

第一次用 .then(),會回傳一個 response

fetch('https://run.mocky.io/v3/2f3916bb-9322-4e0c-bdd8-29d62933be4e').then((res) => {
  console.log(res)
})

response 裡面有 body, headers, status 等等,主要我們要拿資料的地方在 body 裡面。

有兩個常用的 fn,.text() and .json()

res.text() => 回傳值是 text

res.json() => 回傳值是 body 的內容

3. 整理一下,要用 fetch 拿到 api 的資料內容:

//  第一行拿到的是一個 promise
fetch('https://run.mocky.io/v3/2f3916bb-9322-4e0c-bdd8-29d62933be4e')

//  接著用 .then(),裡面放 .json() => JSON.parse()
  .then((res) => {
    return res.json()

//  再一次 .then(),就可以拿到想要的內容了
  }).then((result) => {
    console.log(result)
  })

Fetch 與 Promise 補充系列(二):fetch 的 POST 與錯誤處理

介紹「錯誤處理」、POST 怎麼用?

1. fetch 的錯誤怎麼處理?

1.1 對於 fetch 來說,沒有 response 才算是錯誤;有回應 res: 500 那種都不算錯誤

1.2 try catch 只能用在同步的程式碼裡面,但跟網路有關的都是「非同步」的

1.3 用 .catch (這裡放一個 cb),就可以接住錯誤了;這個跟 try catch 是不一樣的東西!

fetch('https://arun.mocky.io/v3/2f3916bb-9322-4e0c-bdd8-29d62933be4e')
  .then((res) => {
    return res.json()
  }).then((result) => {
    console.log(result)
  }).catch((err) => {
    console.log(err)
  })

2. fetch 的 POST 怎麼用?

2.1 fetch 裡面第一個參數傳網址,第二個傳物件;物件裡面有 method, body 等等

2.2 可切到 network 的 Headers 裡面,看自己寫的 data 內容

2.3 要注意 content-type 的不同,會有不同格式

const apiURL = 'https://run.mocky.io/v3/2f3916bb-9322-4e0c-bdd8-29d62933be4e'
const data = {
  name: 'christy'
}

// fetch (網址 apiURL, {物件})
fetch(apiURL, {
  method: 'POST',
//  如果要傳 json 格式的資料,就要用 stringify()
  body: JSON.stringify(data),

// 如果要傳特定的 header,見下面的參考資料
  headers: {
    'Content-Type': 'application/json',
  }
})
  .then((res) => {
    return res.json()
  }).then((result) => {
    console.log(result)
  }).catch((err) => {
    console.log(err)
  })

參考資料:Uploading JSON data

好像可以用 POST,參考 How to POST json to mocky io


Fetch 與 Promise 補充系列(三):fetch 的使用注意事項

前兩個影片把 fetch 基本用法講完了,這裡要提的是需要特別注意的三個地方

1. content-type:

headers 裡面的 content-type 決定了 server 要怎麼處理 req,如果 body 資料格式不是 json 的話,server 有可能會出錯。

2. credential:

無論是 XHR or fetch,發一個非同樣 domain 的 api (cross-origin),預設是不會帶 cookie 的;如果要帶要在 fetch 裡面自己加這一行:

credentials: 'include'

參考:

Sending a request with credentials included

3. 對於 mode: 'no-cors' 的誤解:

假設要發一個 cross-origin 的 req,如果出現以下錯誤訊息,

'Access to fetch at 'https://lidemy.com/' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.'

就算在 fetch 裡面加上一個 mode: 'no-cors',即使錯誤不見了,也只能拿到一個空的 response。

在 fetch 加上 mode: 'no-cors',是在跟瀏覽器說「我本來就沒有要拿 res,請回傳一個空的 res 給我」,不可能突破 cross-origin 的限制,只有在 server 有加上 header 同意你拿資料的時候,才能拿到東西。

參考:Supplying request options


Fetch 與 Promise 補充系列(四):淺談 Promise

0. promise 是為了解決 call back 地獄的問題,讓語法更簡潔好讀

參考:JavaScript Promise 全介紹

1. Promise 的應用:

例如:剪貼簿也會回傳ㄧ個 Promise

navigator.clipboard.readText().then((text) => {
  console.log(text)
})

2. 怎麼自己做一個 Promise

// b. promise 裡面放的函式,會傳兩個參數,而這兩個參數也會是函式
// resolve, reject 是可以改變名稱的,叫 aa, bb 也行
function init(resolve, reject) {
  resolve(123)
}

// a. 首先 new 一個 promise(很物件導向的寫法),裡面必須放一個函式
const myPromise = new Promise(init)

// c. 接著自己做的 myPromise 就會變成一個 promise 物件,
// 回傳的值有兩種,一種是 resolve(已實現);一種是 reject(已拒絕)
// 已實現裡面會有 value: resolve(value)
// 已拒絕裡面會有 reason: reject(reason)
myPromise.then((data) => {
  console.log('data', data)
}).catch((err) => {
  console.log('err', err)
})

參考資料:Promise 物件的建立

3. 最常見自己做的 promise 長這樣:

const myPromise = new Promise((resolve, reject) => {
  resolve(123)
})

myPromise.then((data) => {
  console.log('data:', data)
}).catch((err) => {
  console.log('err', err)
})
// 這樣會回傳 data: 123

4. promise 的特色:06':50"

4.1 有三種狀態,分別是:

a. pending

b. fulfilled

c. rejected

A Promise is in one of these states

4.2 pending 表示初始狀態,只有兩個可能,不是 fulfilled 就是 rejected;一但這兩種狀態擇一之後,就不會再被改變了。

5. 用 promise 改寫 XHR: 09':38"

可以用 promise 把非同步 / 同步的事件包起來

const myPromise = new Promise((resolve, reject) => {
  var request = new XMLHttpRequest();
  request.open('GET', 'https://run.mocky.io/v3/ac4a8805-ff29-4d0f-9e4a-67eaa73ff3cc', true);

  request.onload = function() {
    if (this.status >= 200 && this.status < 400) {
      var data = JSON.parse(this.response);
      resolve(data)
    }
  };

  request.onerror = function(err) {
    reject(err)
  };

  request.send();
})

myPromise.then((data) => {
  console.log('data:', data)
}).catch((err) => {
  console.log('err', err)
})

6. 設一個 setTimeout,過幾秒再把 promise 傳回去: 12':02"

過幾天好像看懂了,但是要多練習。


Fetch 與 Promise 補充系列(五):async 與 await

用長得像同步的方式包裝非同步語法

await 後面接一個 promise
await 只能在 async fn 裡面執行

簡單來說就是用一個 async fn 把 fetch 抓到的東西包起來,然後用 await 後面接 promise










Related Posts

CH4 字元與字串筆記

CH4 字元與字串筆記

JavaScript 提升(Hoisting)概念

JavaScript 提升(Hoisting)概念

前端必備 JavaScript, jQuery 表示QQ

前端必備 JavaScript, jQuery 表示QQ


Comments