Ajax,2005年誕生的技術,至今已持續了 10 年。它是一種在客戶端創建一個異步請求的技術,本質上它不算創新,是一組技術的組合。它的核心對象是 XMLHttpRequest。
簡單回顧下歷史
- 1996年,IE 中首先添加了 iframe 用來實現異步請求獲取服務器內容
- 1998年,微軟 Outlook 在客戶端 script 中實現了 XMLHttp 對象
- 1999年,微軟在 IE5 中添加了 XMLHTTP ActiveX 對象用來異步獲取服務器內容,該對象直到 Edge 瀏覽器才廢棄。其它瀏覽器陸續實現了類似的對象稱為 XMLHttpRequest
- 2004年,Google Gmail 中大量使用 XMLHttpRequest
- 2005年,Google Map 中大量使用 XMLHttpRequest
- 2005年,Jesse James Garrett 發表了文章 "Ajax: A New Approach to Web Applications",Ajax 誕生
- 2006年,XMLHttpRequest 被 W3C 采納,最后更新時間是 2014年1月
使用步驟大概如下
var xhr = new XMLHttpRequest();
xhr.open('GET', url);
xhr.onload = function() {
// To do with xhr.response
};
xhr.onerror = function() {
// Handling errors
};
xhr.send();
以上可以看出,XHR 使用 onXXX 處理,典型的 "事件模式"。
Fetch 目前還不是 W3C 規范,由 whatag 負責出品。與 Ajax 不同的是,它的 API 不是事件機制,而采用了目前流行的 Promise 方式處理。我們知道 Promise 是已經正式發布的 ES6 的內容之一。
fetch('doAct.action').then(function(res) {
if (res.ok) {
res.text().then(function(obj) {
// Get the plain text
})
}
}, function(ex) {
console.log(ex)
})
以上 fetch 函數是全局的,目前最新的Firefox,Chrome,Opera 都已支持,詳見


以上是一個最簡單的請求,只要傳一個參數 url 過去,默認為 get 請求,獲取純文本,fetch 第二個參數可以進行很多配置,比如 POST 請求
fetch("doAct.action", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded"
},
body: "keyword=榮耀7i&enc=utf-8&pvid=0v3w1kii.bf1ela"
}).then(function(res) {
if (res.ok) {
// To do with res
} else if (res.status == 401) {
// To do with res
}
}, function(e) {
// Handling errors
});
如果返回的是 JSON, 如下
fetch('doAct.action').then(function(res) {
if (res.ok) {
res.json().then(function(obj) {
// Get the JSON
})
}
}, function(ex) {
console.log(ex)
})
res 實際上該規范定義的 Response 對象,它有如下方法
- arrayBuffer()
- blob()
- json()
- text()
- formData()
此外,Fetch 跨域請求時默認不會帶 cookie,需要時得手動指定 credentials: 'include'
fetch('doAct.action', {credentials: 'include'}).then(function(res) {
// ...
})
這和 XHR 的 withCredentials 一樣,只是 withCredentials 只要設為 true。
Fecth 獲取 HTTP 頭信息非常容易
// 取HTTP頭信息
fetch('doAct.action').then(function(response) {
console.log(response.headers.get('Content-Type'));
console.log(response.headers.get('Date'));
});
Fetch 也可以鏈式使用
// 示例4:鏈式調用
function status(response) {
if (response.status >= 200 && response.status < 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}
function json(response) {
return response.json()
}
fetch('doAct.action')
.then(status)
.then(json)
.then(function(data) {
console.log('Request succeeded with JSON response', data);
}).catch(function(error) {
console.log('Request failed', error);
});
Fetch 模擬表單提交
fetch('doAct.action', {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'foo=bar&lorem=ipsum'
})
.then(json)
.then(function (data) {
console.log('Request succeeded with JSON response', data);
})
.catch(function (error) {
console.log('Request failed', error);
});
相關:
https://developer.mozilla.org/zh-CN/docs/Web/API/GlobalFetch/fetch
https://fetch.spec.whatwg.org
https://hacks.mozilla.org/2015/03/this-api-is-so-fetching
