發請求有哪幾種方式:
比較常規來講解
form
表單來發起get
或post
請求,但會刷新頁面a
標籤可以發get
請求,但會刷新頁面img
標籤可以發get
請求,但只能以圖片形式來展示link
標籤可以發get
請求,但只能以css
和favicon
等形式來展示script
標籤可以發get
請求,但只能以腳本形式來執行
如果用 CRUD 的形式來實現:
- get
- post
- put
- delete
在
http
裡,response 是字串
重新認識 Ajax
Ajax 是 Asynchronous JavaScript and XML (異步 JavaScript 和 XML)
Ajax
可以通過 JavaScript
來異步通訊 (client
和 Server
進行通訊)。Ajax
可以在不用刷新整個網頁,可以達到網頁局部更新。也就是說 client
向 server
請求獲取數據來進行網頁上更新,這樣提升用戶體驗。
傳統請求過程
client
會向server
發起request
server
會收到請求後,進行處理您要的東西- 處理完後,
server
將會創建response
- 然後
server
將response
給client
client
收到response
後client
刷新整個頁面來更新數據
根據上面傳統請求過程步驟,我們可以知道這是同步行為。Ajax 可以讓 browser/client
和 server 之間異步通訊。我們可以通過 JavaScript
來發起請求來向 server
獲取數據來操作網頁內容局部更新,無需重刷新整個頁面,帶來用戶體驗效果!
Ajax 優點和缺點
優點
- 減少 bandwidth,減輕
server
負擔, 減少請求,按照需要數據進行請求 - 提高用戶體驗
- …
缺點:
- 對
SEO
不友善 - debug 不友善
- 不支持
browser
back- 問題:
ajax
可以做到無刷新,沒辦法更改URL
,所以browser
不支持前進和後退。以分頁作為例子,當我順序點分頁123,URL
完全沒有變更 (局部請求資源)。我目前在分頁3,可是我點擊後退 (上一頁),照理來說後退回到分頁2,但我只回到最初上一個網址的內容分頁1,而不是分頁2。因為ajax
不能在browser
保留歷史紀錄。link - 解決之一:通過 HTML5 API
history.pushState
或history.replaceState
來操作browser
歷史紀錄和無刷新行為來改變URL
。
- 問題:
- 安全性問題
- …
Ajax 與跨域
只有在同源策略情況下允許發 ajax
請求。
在非同源情況下,使用 ajax
發送請求,由於 ajax
可以讀取 response
內容,所以 browser
認為是不安全,可以發送,但 browser
不會給你響應 (會被擋)。
例子:
https://facebook.com
可以向https://www.facebook.com
發 ajax 請求嗎?
答案:不行
如果我想透過 ajax
跨域呢?
本來 A網站想請求 B網站內容,但他們是不同域,造成無法請求響應。
可以用 cors
來告訴 browser
(A網站)和(B網站)是朋友,A網站要 B網站內容,給他吧。
只要在後端
response header
設定Access-Control-Allow-origin, 指定允許 A網站
。
如果是多個不同域可以這樣設定Access-Control-Allow-origin, *
。
跨域
browser
限制下不允許透過 JS
跨域,所以 ajax
是不被允許。像 browser
本身是沒有限制自己,如 form
, img
, script
, link
, a
等標籤都可以允許與 server
通訊,可以被說成跨域行為。
例子1:
form
表單提交到另一個網站後,原本頁面無法取得新頁面內容,所以browser
是認為安全。例子2:
script
標籤裡,我們可以請求任意不同domain
。我們也知道在同源策略裡只要 (協議,域名,端口) 三個不同就是跨域行為。在回顧跨域和同源策略是什麼,強逼自己記在心裡。
- 同源策略 - 協議,域名,端口 必須相同
- 跨域 - 協議,域名,端口 不相同等同於跨域行為
關於更多 CORS 請到 link
總結
雖然 ajax 真的很方便也非常安全,因為有同源策略 (Same origin policy),只有協議,域名,端口 必須相同。如果非要通過 ajax 來跨域的話,需要後端開啟允許可跨域來告訴 browser
我們是朋友。browser
會根據 response header
裡字段 Access-Control-Allow-Origin
知道你們關係。
面試題
請使用原生 JS 來發送 ajax 請求
答:let request = new XMLHttpRequest() request.open('GET', 'https://jsonplaceholder.typicode.com/todos') // 配置 request.onreadystatechange = function () { if (request.readyState === 4) { console.log('請求response完成') if (request.status >= 200) { console.log('請求成功') let string = request.responseText let data = JSON.parse(string) console.log(data) } else if (request.status >= 400) { console.log('請求失敗') } } } request.send()
JSON 和 JavaScript
答:JSON
不具備程式語言特性,它是數據傳輸格式。 JSON 官方
JSON 和 XML 都是數據格式,相比之下 JSON 可讀性很高,也得到大眾的使用!
-------------------------------------------
JS VS JSON
-------------------------------------------
undefined 沒有
null null
boolean boolean
function f1(){...} 沒有
{name: 'decadehew'} {"name":"decadehew"}
['a', 'b'] ["a", "b"]
'decadehew' "decadehew"
let person = {} 沒有
// ---------------------
// JS convert to JSON
// ---------------------
JSON.stringify({name: 'decadehew'}) // {"name": "decadehew"}
// -----------------------------
// JSON String convert to JS
// 符合 JSON 字串來表示 JS 的值
// -----------------------------
稍微說明:
// '"foo"' 是 JSON 字串,
// parse 會解析 JSON 字串轉換成 JS 的值(字串)。
// 你可以看符合 JSON 字串裡所表示/描述是什麼,它就是 JS 某類型的值!
//
//
// '"foo"' 表示是 JS 字串類型,
// "true" 表示是 boolean 類型,
// {} 表示是 JS 對象類型。
JSON.parse('"foo"') // 'foo'
JSON.parse('true'); // true
JSON.parse({"name": "decadehew"}) // {name: 'decadehew'}