AJAX
概述
背景
“JavaScript 對(duì)我們而已能力有限”乘客,我們目前所了解到的 Web 所提供的 API 都只停留在“單機(jī)游戲”的階段。
例如:
- 無法在實(shí)現(xiàn)用戶登錄功能時(shí)淀歇,當(dāng)用戶輸入郵箱地址顯示用戶對(duì)應(yīng)的頭像
- 無法在實(shí)現(xiàn)用戶注冊功能時(shí)易核,當(dāng)用戶輸入郵箱或者用戶名就提示是否存在
- 無法在實(shí)現(xiàn)留言板功能時(shí),實(shí)時(shí)看到最新的用戶留言
思考:為什么做不到這些呢浪默?
在此之前牡直,我們可以通過以下幾種方式讓瀏覽器發(fā)出對(duì)服務(wù)端的請求,獲得服務(wù)端的數(shù)據(jù):
- 地址欄輸入地址纳决,回車碰逸,刷新
- 特定元素的 href 或 src 屬性
- 表單提交
這些方案都是我們無法通過或者很難通過代碼的方式進(jìn)行編程(對(duì)服務(wù)端發(fā)出請求并且接受服務(wù)端返回的響應(yīng)),如果我們可以通過 JavaScript 直接發(fā)送網(wǎng)絡(luò)請求阔加,那么 Web 的可能就會(huì)更多饵史,隨之能夠?qū)崿F(xiàn)的功能也會(huì)更多,至少不再是只能開發(fā)“單機(jī)游戲”胜榔。
對(duì) XXX 進(jìn)行編程指的就是用代碼的方式操作它胳喷。
Google Suggest
AJAX(Asynchronous JavaScript and XML),最早出現(xiàn)在 2005 年的 Google Suggest夭织,是在瀏覽器端進(jìn)行網(wǎng)絡(luò)編程(發(fā)送請求吭露、接收響應(yīng))的技術(shù)方案,它使我們可以通過 JavaScript 直接獲取服務(wù)端最新的內(nèi)容而不必重新加載頁面尊惰。讓 Web 更能接近桌面應(yīng)用的用戶體驗(yàn)讲竿。
AJAX (Asynchronous Javascript And XML)
說白了纬向,AJAX 就是瀏覽器提供的一套 API,可以通過 JavaScript 調(diào)用戴卜,從而實(shí)現(xiàn)通過代碼控制請求與響應(yīng)逾条。實(shí)現(xiàn)通過 JavaScript 進(jìn)行網(wǎng)絡(luò)編程。
至于 XML:最早在客戶端與服務(wù)端之間傳遞數(shù)據(jù)時(shí)所采用的數(shù)據(jù)格式就是 XML投剥。
能力不夠 API 湊师脂。
應(yīng)用場景總結(jié)
對(duì)于每一個(gè)未知的技術(shù),我們在了解了過后第一反應(yīng)就是在什么情況下用江锨?
- 按需獲取數(shù)據(jù)
- 對(duì)用戶數(shù)據(jù)校驗(yàn)
- 自動(dòng)更新頁面內(nèi)容
- 提升用戶體驗(yàn)吃警,無刷新的體驗(yàn)
快速上手
AJAX API 中核心提供的是一個(gè) XMLHttpRequest
類型,所有的 AJAX 操作都需要使用到這個(gè)類型啄育。
使用 AJAX 的過程可以類比平常我們訪問網(wǎng)頁過程
// 1. 創(chuàng)建一個(gè) XMLHttpRequest 類型的對(duì)象 —— 相當(dāng)于打開了一個(gè)瀏覽器
var xhr = new XMLHttpRequest()
// 2. 打開與一個(gè)網(wǎng)址之間的連接 —— 相當(dāng)于在地址欄輸入訪問地址
xhr.open('GET', '/time')
// 3. 通過連接發(fā)送一次請求 —— 相當(dāng)于回車或者點(diǎn)擊訪問發(fā)送請求
xhr.send(null)
// 4. 指定 xhr 狀態(tài)變化事件處理函數(shù) —— 相當(dāng)于處理網(wǎng)頁呈現(xiàn)后的操作
xhr.onreadystatechange = function () {
// 通過 xhr 的 readyState 判斷此次請求的響應(yīng)是否接收完成
if (this.readyState === 4) {
// 通過 xhr 的 responseText 獲取到響應(yīng)的響應(yīng)體
console.log(this.responseText)
}
}
注意:涉及到 AJAX 操作的頁面不能使用文件協(xié)議訪問(文件的方式訪問)
readyState
由于 readystatechange
事件是在 xhr
對(duì)象狀態(tài)變化時(shí)觸發(fā)(不單是在得到響應(yīng)時(shí))酌心,也就意味著這個(gè)事件會(huì)被觸發(fā)多次,所以我們有必要了解每一個(gè)狀態(tài)值代表的含義:
readyState | 狀態(tài)描述 | 說明 |
---|---|---|
0 | UNSENT | 代理(XHR)被創(chuàng)建挑豌,但尚未調(diào)用 open() 方法安券。 |
1 | OPENED |
open() 方法已經(jīng)被調(diào)用,建立了連接氓英。 |
2 | HEADERS_RECEIVED |
send() 方法已經(jīng)被調(diào)用侯勉,并且已經(jīng)可以獲取狀態(tài)行和響應(yīng)頭。 |
3 | LOADING | 響應(yīng)體下載中铝阐, responseText 屬性可能已經(jīng)包含部分?jǐn)?shù)據(jù)址貌。 |
4 | DONE | 響應(yīng)體下載完成,可以直接使用 responseText 徘键。 |
時(shí)間軸
s=>start: UNSENT
o1=>operation: OPENED
o2=>operation: HEADERS_RECEIVED
o3=>operation: LOADING
e=>end: DONE
s(right)->o1(right)->o2(right)->o3(right)->e
s=>start: 初始化
o1=>operation: 建立連接
o2=>operation: 接收到響應(yīng)頭
o3=>operation: 響應(yīng)體加載中
e=>end: 加載完成
s(right)->o1(right)->o2(right)->o3(right)->e
var xhr = new XMLHttpRequest()
console.log(xhr.readyState)
// => 0
// 初始化 請求代理對(duì)象
xhr.open('GET', '/time')
console.log(xhr.readyState)
// => 1
// open 方法已經(jīng)調(diào)用练对,建立一個(gè)與服務(wù)端特定端口的連接
xhr.send()
xhr.addEventListener('readystatechange', function () {
switch (this.readyState) {
case 2:
// => 2
// 已經(jīng)接受到了響應(yīng)報(bào)文的響應(yīng)頭
// 可以拿到頭
// console.log(this.getAllResponseHeaders())
console.log(this.getResponseHeader('server'))
// 但是還沒有拿到體
console.log(this.responseText)
break
case 3:
// => 3
// 正在下載響應(yīng)報(bào)文的響應(yīng)體,有可能響應(yīng)體為空吹害,也有可能不完整
// 在這里處理響應(yīng)體不保險(xiǎn)(不可靠)
console.log(this.responseText)
break
case 4:
// => 4
// 一切 OK (整個(gè)響應(yīng)報(bào)文已經(jīng)完整下載下來了)
// 這里處理響應(yīng)體
console.log(this.responseText)
break
}
})
通過理解每一個(gè)狀態(tài)值的含義得出一個(gè)結(jié)論:一般我們都是在 readyState
值為 4
時(shí)螟凭,執(zhí)行響應(yīng)的后續(xù)邏輯。
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
// 后續(xù)邏輯......
}
}
遵循 HTTP
本質(zhì)上 XMLHttpRequest 就是 JavaScript 在 Web 平臺(tái)中發(fā)送 HTTP 請求的手段赠制,所以我們發(fā)送出去的請求任然是 HTTP 請求赂摆,同樣符合 HTTP 約定的格式:
// 設(shè)置請求報(bào)文的請求行
xhr.open('GET', '/time')
// 設(shè)置請求頭
xhr.setRequestHeader('Accept', 'text/plain')
// 設(shè)置請求體
xhr.send(null)
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
// 獲取響應(yīng)狀態(tài)碼
console.log(this.status)
// 獲取響應(yīng)狀態(tài)描述
console.log(this.statusText)
// 獲取響應(yīng)頭信息
console.log(this.getResponseHeader('Content-Type')) // 指定響應(yīng)頭
console.log(this.getAllResponseHeaders()) // 全部響應(yīng)頭
// 獲取響應(yīng)體
console.log(this.responseText) // 文本形式
console.log(this.responseXML) // XML 形式,了解即可不用了
}
}
參考鏈接:
具體用法
GET 請求
通常在一次 GET 請求過程中钟些,參數(shù)傳遞都是通過 URL 地址中的
?
參數(shù)傳遞烟号。
var xhr = new XMLHttpRequest()
// GET 請求傳遞參數(shù)通常使用的是問號(hào)傳參
// 這里可以在請求地址后面加上參數(shù),從而傳遞數(shù)據(jù)到服務(wù)端
xhr.open('GET', '/delete?id=1')
// 一般在 GET 請求時(shí)無需設(shè)置響應(yīng)體政恍,可以傳 null 或者干脆不傳
xhr.send(null)
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
console.log(this.responseText)
}
}
// 一般情況下 URL 傳遞的都是參數(shù)性質(zhì)的數(shù)據(jù)汪拥,而 POST 一般都是業(yè)務(wù)數(shù)據(jù)
POST 請求
POST 請求過程中,都是采用請求體承載需要提交的數(shù)據(jù)篙耗。
var xhr = new XMLHttpRequest()
// open 方法的第一個(gè)參數(shù)的作用就是設(shè)置請求的 method
xhr.open('POST', '/add')
// 設(shè)置請求頭中的 Content-Type 為 application/x-www-form-urlencoded
// 標(biāo)識(shí)此次請求的請求體格式為 urlencoded 以便于服務(wù)端接收數(shù) 據(jù)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 需要提交到服務(wù)端的數(shù)據(jù)可以通過 send 方法的參數(shù)傳遞
// 格式:name=zhangsan&age=18
xhr.send('name=zhangsan&age=18')
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
console.log(this.responseText)
}
}
同步與異步
關(guān)于同步與異步的概念在生活中有很多常見的場景迫筑,舉例說明宪赶。
- 同步:一個(gè)人在同一個(gè)時(shí)刻只能做一件事情,在執(zhí)行一些耗時(shí)的操作(不需要看管)不去做別的事脯燃,只是等待
- 異步:在執(zhí)行一些耗時(shí)的操作(不需要看管)去做別的事搂妻,而不是等待
xhr.open()
方法第三個(gè)參數(shù)要求傳入的是一個(gè) bool
值,其作用就是設(shè)置此次請求是否采用異步方式執(zhí)行辕棚,默認(rèn)為 true
欲主,如果需要同步執(zhí)行可以通過傳遞 false
實(shí)現(xiàn):
console.log('before ajax')
var xhr = new XMLHttpRequest()
// 默認(rèn)第三個(gè)參數(shù)為 true 意味著采用異步方式執(zhí)行
xhr.open('GET', '/time', true)
xhr.send(null)
xhr.onreadystatechange = function () {
if (this.readyState === 4) {
// 這里的代碼最后執(zhí)行
console.log('request done')
}
}
console.log('after ajax')
如果采用同步方式執(zhí)行,則代碼會(huì)卡死在 xhr.send()
這一步:
console.log('before ajax')
var xhr = new XMLHttpRequest()
// 同步方式
xhr.open('GET', '/time', false)
// // 同步方式 執(zhí)行需要 先注冊事件再調(diào)用 send逝嚎,否則 readystatechange 無法觸發(fā)
// xhr.onreadystatechange = function () {
// if (this.readyState === 4) {
// // 這里的代碼最后執(zhí)行
// console.log('request done')
// }
// }
xhr.send(null)
// 因?yàn)?send 方法執(zhí)行完成 響應(yīng)已經(jīng)下載完成
console.log(xhr.responseText)
console.log('after ajax')
演示同步異步差異扁瓢。
了解同步模式即可,切記不要使用同步模式补君。
至此引几,我們已經(jīng)大致了解了 AJAX 所的提供的基本 API 。
XMLHttpRequest API 總結(jié)
屬性
-
readyState
xhr的狀態(tài) 4 響應(yīng)體接收完畢 -
status
獲取狀態(tài)碼 -
responseText
獲取響應(yīng)體挽铁,文本格式 -
responseXML
獲取響應(yīng)體伟桅,xml格式 -
onreadystatechange
事件,當(dāng)xhr.readyState屬性發(fā)生改變觸發(fā)
方法
-
open(method, url, async)
設(shè)置請求的方式屿储,請求的路徑贿讹, 同步 false/異步 true -
send(requsetBody)
發(fā)送請求(體) -
setRequestHeader(key, value)
設(shè)置請求頭 -
getResponseHeader(key)
獲取響應(yīng)頭
響應(yīng)數(shù)據(jù)格式
提問:如果希望服務(wù)端返回一個(gè)復(fù)雜數(shù)據(jù)渐逃,該如何處理够掠?
關(guān)心的問題就是服務(wù)端發(fā)出何種格式的數(shù)據(jù),這種格式如何在客戶端用 JavaScript 解析茄菊。
XML
一種數(shù)據(jù)描述手段
老掉牙的東西疯潭,簡單演示一下,不在這里浪費(fèi)時(shí)間面殖,基本現(xiàn)在的項(xiàng)目不用了竖哩。
淘汰的原因:數(shù)據(jù)冗余太多
JSON
也是一種數(shù)據(jù)描述手段,類似于 JavaScript 字面量方式
服務(wù)端采用 JSON 格式返回?cái)?shù)據(jù)脊僚,客戶端按照 JSON 格式解析數(shù)據(jù)相叁。
注意:
- 不管是 JSON 也好,還是 XML辽幌,只是在 AJAX 請求過程中用到增淹,并不代表它們與 AJAX 之間有必然的聯(lián)系,它們只是數(shù)據(jù)協(xié)議罷了乌企。
- 不管服務(wù)端是采用 XML 還是采用 JSON 本質(zhì)上都是將數(shù)據(jù)返回給客戶端虑润。
- 服務(wù)端應(yīng)該根據(jù)響應(yīng)內(nèi)容的格式設(shè)置一個(gè)合理的 Content-Type。
緩存問題
緩存問題指的是:多次 AJAX GET 請求同一個(gè) URL 得到的結(jié)果是相同的加酵,目前絕大多數(shù)瀏覽器已經(jīng)沒有這個(gè)問題了拳喻,只有早期的 IE 瀏覽器存在這個(gè)問題
var xhr = new XMLHttpRequest()
xhr.open('GET', '/time')
xhr.send(null)
xhr.onreadystatechange = function () {
if (this.readyState !== 4) return
console.log(this.responseText)
// => 每次得到的結(jié)果都是相同的
}
解決方案
URL 加戳
這個(gè)辦法的核心就是讓瀏覽器認(rèn)為每次請求的地址都是不同的哭当。
不同的 querystring 會(huì)被瀏覽器認(rèn)為是不同的地址,瀏覽器會(huì)忽略客戶端緩存冗澈。
var xhr = new XMLHttpRequest()
xhr.open('GET', '/time?t=' + Date.now())
xhr.send(null)
xhr.onreadystatechange = function () {
if (this.readyState !== 4) return
console.log(this.responseText)
// =>
}
*服務(wù)端設(shè)置響應(yīng)頭
由服務(wù)端通過 HTTP 響應(yīng)報(bào)文中的響應(yīng)頭告知客戶端瀏覽器不要緩存當(dāng)前地址钦勘。
app.get('/time', (req, res) => {
res.setHeader('Cache-Control', 'no-cache')
res.setHeader('Pragma', 'no-cache')
res.setHeader('Expires', '-1')
res.send(Date.now().toString())
})
了解即可,更多的情況下前端開發(fā)中還是通過加戳的方式解決此問題亚亲,因?yàn)樵谇岸丝煽胤秶畠?nèi)个盆。
兼容方案
XMLHttpRequest 在老版本瀏覽器(IE5/6)中有兼容問題,可以通過另外一種方式代替朵栖。
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
// xhr 的成員相同
留言板案例
- 頁面結(jié)構(gòu)
- 數(shù)據(jù)接口
- AJAX 實(shí)現(xiàn)
處理響應(yīng)數(shù)據(jù)渲染
客戶端中拿到請求的數(shù)據(jù)過后最常見的就是把這些數(shù)據(jù)呈現(xiàn)到界面上颊亮。
如果數(shù)據(jù)結(jié)構(gòu)簡單,可以直接通過字符串操作(拼接)的方式處理陨溅,但是如果數(shù)據(jù)過于復(fù)雜终惑,字符串拼接維護(hù)成本太大,就不推薦了门扇。
模板引擎:
- artTemplate:https://aui.github.io/art-template/
模板引擎實(shí)際上就是一個(gè) API雹有,模板引擎有很多種,使用方式大同小異臼寄,目的為了可以更容易的將數(shù)據(jù)渲染到HTML字符串中霸奕。
封裝
AJAX 請求封裝
函數(shù)就可以理解為一個(gè)想要做的事情,函數(shù)體中約定了這件事情做的過程吉拳,直到調(diào)用時(shí)才開始工作质帅。
/**
* 發(fā)送一個(gè) AJAX 請求
* @param {String} url 請求地址
* @param {String} method 請求方法
* @param {Object} params 請求參數(shù)
* @param {Function} done 請求完成過后需要做的事情(委托/回調(diào))
*/
function ajax (url, method, params, done) {
// 統(tǒng)一轉(zhuǎn)換為大寫便于后續(xù)判斷
method = method.toUpperCase()
// 對(duì)象形式的參數(shù)轉(zhuǎn)換為 urlencoded 格式
var pairs = []
for (var key in params) {
pairs.push(key + '=' + params[key])
}
var querystring = pairs.join('&')
var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP')
xhr.addEventListener('readystatechange', function () {
if (this.readyState !== 4) return
// 嘗試通過 JSON 格式解析響應(yīng)體
try {
done(JSON.parse(this.responseText))
} catch (e) {
done(this.responseText)
}
})
// 如果是 GET 請求就設(shè)置 URL 地址 問號(hào)參數(shù)
if (method === 'GET') {
url += '?' + querystring
}
xhr.open(method, url)
// 如果是 POST 請求就設(shè)置請求體
var data = null
if (method === 'POST') {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
data = querystring
}
xhr.send(data)
}
ajax('get', '/getsomthing', { id: 123 }, function (data) {
console.log(data)
})
ajax('post', '/addsomthing', { foo: 'posted data' }, function (data) {
console.log(data)
})
委托:將函數(shù)作為參數(shù)傳遞就像是將一個(gè)事情交給別人,這就是委托的概念
jQuery 中的 AJAX
jQuery 中有一套專門針對(duì) AJAX 的封裝留攒,功能十分完善煤惩,經(jīng)常使用,需要著重注意炼邀。
一個(gè)你會(huì)用我會(huì)用他會(huì)用到的點(diǎn)魄揉,就一定有一個(gè)已經(jīng)封裝好的
參考:
$.ajax
$.ajax({
url: '/time',
type: 'get',
dataType: 'json',
data: { id: 1 },
beforeSend: function (xhr) {
console.log('before send')
},
success: function (data) {
console.log(data)
},
error: function (xhr) {
console.log(xhr)
},
complete: function (xhr) {
console.log('request completed')
}
})
常用選項(xiàng)參數(shù)介紹:
- url:請求地址
- type:請求方法,默認(rèn)為
get
- dataType:服務(wù)端響應(yīng)數(shù)據(jù)類型
- contentType:請求體內(nèi)容類型拭宁,默認(rèn)
application/x-www-form-urlencoded
- data:需要傳遞到服務(wù)端的數(shù)據(jù)洛退,如果 GET 則通過 URL 傳遞,如果 POST 則通過請求體傳遞
- timeout:請求超時(shí)時(shí)間
- beforeSend:請求發(fā)起之前觸發(fā)
- success:請求成功之后觸發(fā)(響應(yīng)狀態(tài)碼 200)
- error:請求失敗觸發(fā)
- complete:請求完成觸發(fā)(不管成功與否)
$.get
GET 請求快捷方法
$.get(url, data, callback)
$.post
POST 請求快捷方法
$.post(url, data, callback)
全局事件處理
http://www.jquery123.com/category/ajax/global-ajax-event-handlers/
自學(xué)內(nèi)容(作業(yè))
$(selector).load()
$.getJSON()
$.getScript()
簡單概括以上方法的作用和基本用法杰标。
Axios
Axios 是目前應(yīng)用最為廣泛的 AJAX 封裝庫兵怯,相對(duì)于 jQuery 的優(yōu)勢在于功能能強(qiáng)勁,職責(zé)更單一在旱,后期專門有介紹摇零。
axios.get('/time')
.then(function (res) {
console.log(res.data)
})
.catch(function (err) {
console.error(err)
})
*擴(kuò)展:https://github.com/axios/axios
跨域
相關(guān)概念
同源策略是瀏覽器的一種安全策略,所謂同源是指域名,協(xié)議驻仅,端口完全相同谅畅,只有同源的地址才可以相互通過 AJAX 的方式請求。
同源或者不同源說的是兩個(gè)地址之間的關(guān)系噪服,不同源地址之間請求我們稱之為跨域請求
什么是同源毡泻?例如:http://www.example.com/detail.html 與一下地址對(duì)比
對(duì)比地址 | 是否同源 | 原因 |
---|---|---|
http://api.example.com/detail.html | 不同源 | 域名不同 |
https://www.example.com/detail.html | 不同源 | 協(xié)議不同 |
http://www.example.com:8080/detail.html | 不同源 | 端口不同 |
http://api.example.com:8080/detail.html | 不同源 | 域名、端口不同 |
https://api.example.com/detail.html | 不同源 | 協(xié)議粘优、域名不同 |
https://www.example.com:8080/detail.html | 不同源 | 端口仇味、協(xié)議不同 |
http://www.example.com/other.html | 同源 | 只是目錄不同 |
解決方案
現(xiàn)代化的 Web 應(yīng)用中肯定會(huì)有不同源的現(xiàn)象,所以必然要解決這個(gè)問題雹顺,從而實(shí)現(xiàn)跨域請求丹墨。
JSONP
JSON with Padding,是一種借助于 script
標(biāo)簽發(fā)送跨域請求的技巧嬉愧。
其原理就是在客戶端借助 script
標(biāo)簽請求服務(wù)端的一個(gè)地址贩挣,服務(wù)端的這個(gè)地址返回一段帶有調(diào)用某個(gè)全局函數(shù)調(diào)用的 JavaScript 腳本(而非一段 HTML),將原本需要返回給客戶端的數(shù)據(jù)通過參數(shù)傳遞給這個(gè)函數(shù)没酣,函數(shù)中就可以得到原本服務(wù)端想要返回的數(shù)據(jù)王财。
以后絕大多數(shù)情況都是采用 JSONP 的手段完成不同源地址之間的跨域請求
客戶端 http://www.zce.me/users-list.html
<script src="http://api.zce.me/users?callback=foo"></script>
服務(wù)端 http://api.zce.me/users?callback=foo 返回的結(jié)果
foo(['我', '是', '你', '原', '本', '需', '要', '直', '接', '返', '回', '的', '數(shù)', '據(jù)'])
總結(jié)一下:由于 XMLHttpRequest 無法發(fā)送不同源地址之間的跨域請求,所以我們必須要另尋他法裕便,script 這種方案就是我們最終選擇的方式绒净,我們把這種方式稱之為 JSONP,如果你不了解原理偿衰,先記住怎么用挂疆,多用一段時(shí)間再來看原理。
問題:
- JSONP 需要服務(wù)端配合哎垦,服務(wù)端按照客戶端的要求返回一段 JavaScript 調(diào)用客戶端的函數(shù)
- 只能發(fā)送 GET 請求
注意:JSONP 用的是 script 標(biāo)簽囱嫩,更 AJAX 提供的 XMLHttpRequest 沒有任何關(guān)系!B┥琛!
jQuery 中對(duì) JSONP 的支持
jQuery 中使用 JSONP 就是將 dataType 設(shè)置為 jsonp
$.ajax({
url: 'https://douban.uieee.com/v2/comming_soon',
type: 'get',
dataType: 'json',
data: { id: 1 },
beforeSend: function (xhr) {
console.log('before send')
},
success: function (data) {
console.log(data)
},
error: function (xhr) {
console.log(xhr)
},
complete: function (xhr) {
console.log('request completed')
}
})
Axios 由于設(shè)計(jì)原因不支持 JSONP
CORS
Cross Origin Resource Share今妄,跨域資源共享
app.get('/time', (req, res) => {
// // 允許任意源訪問郑口,不安全
// res.set('Access-Control-Allow-Origin', '*')
// 允許指定源訪問
res.set('Access-Control-Allow-Origin', 'http://zce.me')
res.send(Date.now().toString())
})
這種方案無需客戶端作出任何變化(客戶端不用改代碼),只是在被請求的服務(wù)端響應(yīng)的時(shí)候添加一個(gè) Access-Control-Allow-Origin
的響應(yīng)頭盾鳞,表示這個(gè)資源是否允許指定域請求犬性。
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
XMLHttpRequest 2.0
暫作了解,無需著重看待
HTML5 中對(duì) XMLHttpRequest 類型全面升級(jí)腾仅,更易用乒裆,更強(qiáng)大
response 屬性
onload / onprogress
var xhr = new XMLHttpRequest()
xhr.open('GET', '/time')
xhr.onload = function () {
// onload readyState => 4
// 只在請求完成時(shí)觸發(fā)
console.log(this.readyState)
}
xhr.onprogress = function () {
// onprogress readyState => 3
// 只在請求進(jìn)行中觸發(fā)
console.log(this.readyState)
}
xhr.send(null)
FormData
以前 AJAX 操作只能提交字符串,現(xiàn)在可以提交 二進(jìn)制 的數(shù)據(jù)
案例
異步上傳文件