iT邦幫忙

2022 iThome 鐵人賽

DAY 15
0
自我挑戰組

SPYxFRONTEND ~ 懂一點後端真是讓人哇哭哇哭系列 第 15

[Day15] 要怎麼知道要 call 的 API url 是?那你必須先知道 routes

  • 分享至 

  • xImage
  •  

前言

一樣開始前請記得在 local 端開好前端、後段:
後端:json-server --watch db.json --port 10000
前端:npm start

本日正文

前幾天都圍繞在 axios 的 CRUD 上,
語法大概長這樣:

axios.get('http://localhost:10000/posts')
axios.post('http://localhost:10000/posts/', {
  id: 4,
  title: '我是第4篇文章',
  author: 'Misado'
})
axios.patch('http://localhost:10000/posts/6', {
  title: '我是第6篇文章 0914修改',
})
axios.delete(`http://localhost:10000/posts/${id}`)

無論是哪個動作,都需要帶 url
而我們下的都是 絕對位址, (EX. http://localhost:10000)
但實際上前端不太會這樣下,
是因為:

  1. 假設 server 的 domain 換掉,
    你就得來把 call 的 url 換掉,
    那換一次就得改一次。
    (雖然理論上不會常換就是了,但是光需要換就是一件麻煩事了。)

  2. 前端通常不是去 call 遠端的 API,(通常前後端是住一起)
    所以不需要 call 到絕對位址

那問題來了,
前端該怎麼 call 跟它同一台 server 的 API url 呢?

常見的 API url:/api/v1

也許有 call 過 API 經驗的人或是在一些範例看過像是以下這樣的 url:
/api/v1/posts
/api/v1/order
/api/v1/PlantEpidemicType

後端 API url 通常都會是 /api/v1 開頭,
(要訂成別的當然也可以,但這應該已經是約定俗成了)
這個就是相對位址的概念哦,
當然該怎麼訂是後端的工作,
而訂完後端會跟前端說你要怎麼 call API,
例如你要取得會員資料要 call /api/v1/member
要取得訂單資料要 call /api/v1/order ...等等。

雖然前端不用知道怎麼訂 url,
但為了要讓我們自己可以試 call 這樣的 url,
我們就自己來試試看吧!

routes:讓你可以自訂 API url

JSON server 有提供 routes 的功能,
官方文件有寫設定 routes 的教學,
那我們先跟著做做看,
首先準備一個 routes.json

{
  "/api/*": "/$1",
}

設定完了,起 API 時記得下參數讓它吃到 routes 的設定,
像這樣:

json-server --watch db.json --port 10000 --routes routes.json

官方文件還有提到,
如果 routes 這樣設定,
那麼你的 url 下 /api/posts 就可以存取到 /posts
也就是 /api/ 後面接怎樣的參數你就會可以存取到怎樣的資訊,
像這樣:

/api/posts # → /posts
/api/posts/1  # → /posts/1

因此我們可以先到瀏覽器這樣下下看:
http://localhost:10000/posts => 原本是這樣下
http://localhost:10000/api/posts => 新的下法

https://ithelp.ithome.com.tw/upload/images/20220916/20129873qQmz0TYFs1.png
看起來都可以存取到一樣的資料。

那我們現在就來改 axios.get 的 url,
原本是這樣寫的:axios.get('http://localhost:10000/posts')
那我們改寫一下,像這樣:

const hostUrl = "http://localhost:10000";
... (略)
function fetchData(){
    axios.get(`${hostUrl}/api/posts`)
      .then(function (response) {
          console.log(response);
          setdataResult(response.data);
          setDataFetchTimes(dataFetchTimes+1);
      })
      .catch(function (error) {
          alert("抓取資料錯誤,請確認後再試");
          console.log(error);
      })
  }

看起來沒有問題,
但我這邊要先說明一下,
url 我暫時這樣寫 axios.get(`${hostUrl}/api/posts`)
不然會導致 call 不到 API,
這邊就小小試一下如果 axios.get('/api/posts') 只這樣 call 會發生什麼事↓
https://ithelp.ithome.com.tw/upload/images/20220916/20129873tX9jLbKyxi.png

(因此一般通常來說 host 不需要寫,
在 server 或哪邊會進行設定,
不過我目前也不知道要在哪設定,
所以這邊的 /api/ 前面還是有先帶 host。)


以上測試 OK 之後我們把 routes.json 改成 /api/v1 試試看,
像這樣:

{
    "/api/v1/*": "/$1"
}

改完之後重起 JSON server,
那前端的語法我們先故意不要改試試看:
https://ithelp.ithome.com.tw/upload/images/20220916/201298731OCqhGQqml.png

沒錯,現在是 call 不到的哦,
因為 API 現在只接收 /api/v1 開頭的語法,
那我們把前端語法改對試試看:

axios.get(`${hostUrl}/api/v1/posts`)

https://ithelp.ithome.com.tw/upload/images/20220916/20129873blkIQBRGgv.png

看起來就沒有問題了~
(PS. 可以用 console.log(response) 看 request 裡的 reponseURL 來確定 call 的 API url,
之後 call API 遇到問題都鼓勵 console.log 印出來看,拿來 trouble shooting 很好用)

那現在我們就把前幾天的 post, patch, delete 都改成新的 url 試試看,
像這樣:

axios.post(`${hostUrl}/api/v1/posts/`, {
  id: 7,
  title: '我是第7篇文章',
  author: 'Misado'
})
axios.patch(`${hostUrl}/api/v1/posts/6`, {
  title: '我是第6篇文章 0916修改',
})
axios.delete(`${hostUrl}/api/v1/posts/${id}`)

看起來都成功了,表示我們 call 的 url 沒有問題~

我會想特別拿 routes 出來講是因為,
之前後端大大就告訴我就這樣 call axios.get('/api/v1/....')
還有要傳入的資料格式,
但一開始我根本不知道 /api/v1/ 是什麼意思,
然後就在自己開 API 試寫的時候也終於搞清楚了,
通常後端 API 都會提供像 axios.get('/api/v1/....') 這樣的 url 供前端 call,
這樣我們以後看到 /api/v1 就會知道是 API 的 url。
所以也把這段拿出來分享這樣~

前端應該是不用知道 routes 的設定之類的,
現在的情境只是因為我們自己起簡單的 API 來玩玩看所以才需要設,
因此今日重點不是擺在怎麼設 routes 哦!

今天是不是又更了解前端怎麼 call API 了呢?
那我們明天再見囉~~~

參考文章

Add custom routes
json-server cannot access via local IP

後記

今天終於來到一半orz


上一篇
[Day14] 用 axios.delete 會把資料刪光光嗎?
下一篇
[Day16] call API 會用的參數系列~用 filter 來限制條件吧!
系列文
SPYxFRONTEND ~ 懂一點後端真是讓人哇哭哇哭30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言