API & AJAX
API
Application Programming Interface
目的
- 降低耦合性 (單一原則)
- 跨系統串接 (不同作業系統,不同程式語言)
- 簡化使用方式 (封裝)
URL
組成
https://www.google.com/?s=hello
https
通訊協定
www.google.com
網址
?s=hello
參數
請求方式
- GET
- POST
- PUT (有定義未實作)
- DELETE (有定義未實作)
對應 CRUD
類型 | C | R | U | D |
---|---|---|---|---|
全名 | Create | Read | Update | Delete |
HTTP | POST/PUT | GET | POST/PUT | DELETE |
SQL | INSERT | SELECT | UPDATE | DELETE |
Web API
每次都請求都是一個 API 的發起與完成
flowchart LR A[Browser] B[Google] C[Backend] A-->| Request Method With URL | B B-->| Run Process | C C-->| Return | B B-->| Response | A
將 Browser
這個視覺化的角色拿掉,發起 Request
就是大眾所謂的 API
通常
Response
會使用JSON
格式回傳
初體驗
觀察兩個網址回應差別
https://book.niceinfos.com/frontend/api/
https://book.niceinfos.com/frontend/api/?action=demo
Ajax
Asnychronous JavaScript And XML
同步與非同步
flowchart LR A[Browser] B[Google] C[Backend] A-->| Request Method With URL | B B-->| Run Process | C C-->| Return after 10s | B B-->| Response | A
在等待的時候,還可以點畫面其他的互動嗎?
非同步請求
html
<button id="btn">AJAX</button>
<div id="response"></div>
js
let btn = document.querySelector('#btn')
let response = document.querySelector('#response')
btn.addEventListener('click', doAjax)
function doAjax() {
let request = new XMLHttpRequest()
request.addEventListener('load', () => {
response.innerHTML = request.responseText
})
request.open('GET', 'https://book.niceinfos.com/frontend/api/?action=demo')
request.send()
}
透過此方法,就算請求需要時間,也不會影響主畫面的操作 (背景作業)
模擬主機端睡眠
- 使用上面的範例,將
url
改為https://book.niceinfos.com/frontend/api/?action=sleep
- 觀察
開發者工具 > 網路
fetch
原本的 XMLHttpRequest
使用上不夠直覺,ES6 之後推出包裝過後的 fetch
方便使用
js
function doAjax() {
let api = 'https://book.niceinfos.com/frontend/api/?action=demo';
fetch(api)
.then((response) => {
return response.text()
// return response.json()
})
.then((data) => {
console.log(data)
})
}
response.text()
將回傳資料解析為純文字
response.json()
將回傳資料解析為 json
POST 發送
js
function doAjax() {
let api = 'https://book.niceinfos.com/frontend/api/'
let params = {
action: 'demo',
data: { a: 1, b: 2 },
}
let options = {
method: 'POST',
body: JSON.stringify(params),
}
fetch(api, options)
.then((response) => {
return response.text()
// return response.json()
})
.then((data) => {
response.innerHTML = data
console.log(data)
})
}
params
傳送資料
options
設定選項
- method
請求方式,預設 GET
- body
請求主體,GET
不可以使用此屬性,透過序列化將資料打為 json
格式發送
關於 then
fetch
本身的包裝是希望讓開發者透過類同步的開發方式寫程式,所以使用 then
來等待非同步
底層使用的是 Promise
物件來處理
檔案上傳
html
<input type="file" id="file" />
<button id="btn">Upload</button>
<div id="response"></div>
js
let btn = document.querySelector('#btn')
let response = document.querySelector('#response')
btn.addEventListener('click', doAjax)
function doAjax() {
let domFile = document.querySelector('#file')
let file = domFile.files[0]
if (!file) {
return
}
let api = 'https://book.niceinfos.com/frontend/api/'
let form = new FormData()
form.append('action', 'upload')
form.append('file', file)
let options = {
method: 'POST',
body: form,
}
fetch(api, options)
.then((response) => {
return response.text()
// return response.json()
})
.then((data) => {
response.innerHTML = data
console.log(data)
})
}
使用 FormData
物件傳送檔案,因為檔案是二進制格式,不可序列化為文字
練習
雲端儲存版 Todo List
將先前開發好的本地儲存版 Todo List 近一步改良
- 新增雲端儲存功能
- 新增雲端載入功能
tip
- 儲存功能對應請求方式為
POST
,請求API
為https://book.niceinfos.com/frontend/api/
- 載入功能對應請求方式為
GET
請求API
為https://book.niceinfos.com/frontend/api/?action=todo&uid=your_uid