本篇是 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 同意你拿資料的時候,才能拿到東西。
Fetch 與 Promise 補充系列(四):淺談 Promise
0. promise 是為了解決 call back 地獄的問題,讓語法更簡潔好讀
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