關於ajax,一我的盡皆知的祕密是,它的基礎API:XMLHttpRequest,用它來作ajax請求實在是不太合適。咱們已經在創造一個優雅的,關於xhr的一些API上作得很好了,可是咱們能作得更好,而能讓咱們作得更好的就是使用fetch API!下面咱們一塊兒簡單地看看這個新增的window.fetch方法,目前已經能夠在Firefox和Chrome Canary上使用了。(注:如今已經能夠在最新的Chrome穩定版本上使用)javascript
在我看來XHR有點兒複雜了,並且我有點想吐槽的是,爲何XML是大寫的,Http倒是小寫的???不管如何,這就是如今你用XHR時的寫法:html
//XHR,簡直了。。。
if(window.XMLHttpRequest){
//Mozilla,Safari...
request = new XMLHttpRequest();
}else if(window.ActiveXObject){
//IE下
try{
request = new ActiveXObject('Msxml2.XMLHTTP');
}
catch(e){
try{
request = new ActiveXObject('Microsoft.XMLHTTP');
}
catch(e){}
}
}
//而後就是open,send
request.open('GET','https://davidwalsh.name/ajax-endpoint',true);
request.send(null);
複製代碼
固然咱們的js框架讓咱們使用XHR的方式變得更優雅了,可是從上面的例子你能夠看出XHR真是一團糟。html5
在全局window做用域如今就提供了fetch方法,第一個參數是一個URL:java
//url參數是必須的,而options是可選的
fetch('https://davidwalsh.name/some/url', {
method: 'get'
}).then(function(response) {
}).catch(function(err) {
// Error :(
});
複製代碼
和最新的Battery API很像,fetch API 是使用Promise去處理結果或者回調的:git
// 簡單的響應處理
fetch('https://davidwalsh.name/some/url').then(function(response) {
}).catch(function(err) {
// Error :(
});
// 掛上更「高級」的處理邏輯
fetch('https://davidwalsh.name/some/url').then(function(response) {
return //...
}).then(function(returnedValue) {
// ...
}).catch(function(err) {
// Error :(
});
複製代碼
若是你不習慣使用then,最好仍是習慣一下吧。。。它很快就會無處不在github
可以設置請求頭對請求的靈活性來講很重要。你可使用new Headers()來建立一個請求頭ajax
// 建立一個空的請求頭實例
var headers = new Headers();
// 添加一些頭部字段
headers.append('Content-Type', 'text/plain');
headers.append('X-My-Custom-Header', 'CustomValue');
// 檢查、獲取和設置頭部的字段
headers.has('Content-Type'); // true
headers.get('Content-Type'); // "text/plain"
headers.set('Content-Type', 'application/json');
// 刪除一個頭部字段
headers.delete('X-My-Custom-Header');
// 添加初始化信息
var headers = new Headers({
'Content-Type': 'text/plain',
'X-My-Custom-Header': 'CustomValue'
});
複製代碼
你能夠用append
,has
,get
,set
和delete
方法去更改請求頭。能夠經過建立一個請求實例去使用這個請求頭。json
var request = new Request('https://davidwalsh.name/some-url', {
headers: new Headers({
'Content-Type': 'text/plain'
})
});
fetch(request).then(function() { /* 處理響應 */ });
複製代碼
咱們來看看Request和Response作了些什麼吧!promise
一個 Request
實例表明着一個 fetch
方法調用的片斷。經過交給 fetch
一個 Request
對象你能夠建立一個高級的、定製的請求:緩存
Headers
對象有關一個簡單的Request 用起來起來就像:
var request = new Request('https://davidwalsh.name/users.json', {
method: 'POST',
mode: 'cors',
redirect: 'follow',
headers: new Headers({
'Content-Type': 'text/plain'
})
});
// 如今,使用它!
fetch(request).then(function() { /* 處理響應 */ });
複製代碼
只有第一個參數url是必須的。全部的屬性會在Request實例建立後變成只讀的狀態。須要留意的是 Request
有一個 clone
方法,當在Service Worker API 中使用 fetch
時這個方法很是重要。由於一個 Request
是一個stream
,當另一個fetch
調用時必須被克隆。
fetch
方法的用法,表現得就像 Request
同樣,因此你能夠這樣作:
fetch('https://davidwalsh.name/users.json', {
method: 'POST',
mode: 'cors',
redirect: 'follow',
headers: new Headers({
'Content-Type': 'text/plain'
})
}).then(function() { /* 處理響應 */ });
複製代碼
在Service Worker中你可能只會用到Request
實例,由於Request
和fetch
的用法能夠說是同樣的。
fetch
的then
方法提供了一個Response
實例,但你能夠手動建立一個Response對象——一種你可能會在使用service workers時遇到的狀況。你能夠這樣設置Response
:
url
是否是最後的URL// 建立你本身的響應,以測試Service worker
// new Response(BODY, OPTIONS)
var response = new Response('.....', {
ok: false,
status: 404,
url: '/'
});
// fetch的then方法會拿到一個Response 實例
fetch('https://davidwalsh.name/')
.then(function(responseObj) {
console.log('status: ', responseObj.status);
});
複製代碼
Response 對象也提供了這些方法:
resolve
resolve
resolve
resolve
USVString
(text)的resolve
當你建立了一個請求,而請求的是JSON,那麼它所獲得的回調函數將具備把原始數據轉換爲JavaScript對象的json
方法
fetch('https://davidwalsh.name/demo/arsenal.json').then(function(response) {
// Convert to JSON
return response.json();
}).then(function(j) {
// 沒錯,j是個JavaScript 對象
console.log(j);
});
複製代碼
固然了,這就是一個簡單的JSON.parse(jsonString),不過使用json
方法是一條方便的捷徑。
JSON 不會一直是咱們指望的響應格式,因此這邊你能夠看看怎麼處理文本或者HTML響應。
fetch('/next/page')
.then(function(response) {
return response.text();
}).then(function(text) {
// <!DOCTYPE ....
console.log(text);
});
複製代碼
你能夠經過在text()
方法後連接上Promise的 then
方法來得到響應文本。
若是你想經過 fetch
來加載一張圖片,就會有點區別,舉個栗子:
fetch('https://davidwalsh.name/flowers.jpg')
.then(function(response) {
return response.blob();
})
.then(function(imageBlob) {
document.querySelector('img').src = URL.createObjectURL(imageBlob);
});
複製代碼
響應的Blob()
方法接受一個Response流並將其讀取完成。
另一個一般會使用AJAX的狀況就是發送From Data,這裏咱們來看看怎麼用 fetch
方法來發送From Data:
fetch('https://davidwalsh.name/submit-json', {
method: 'post',
body: JSON.stringify({
email: document.getElementById('email').value,
answer: document.getElementById('answer').value
})
});
複製代碼
很是的簡單,很是的賞心悅目!
或許 fetch
是一個更好的API,但這個API目前不支持取消請求,這會讓不少開發者對它失望。
看起來使用這個新的 fetch
API比起使用XHR來講更明智,更簡單,託他的福咱們能夠更正確的去實現AJAX。fetch
有着「過後諸葛亮」的優點,儘管 fetch
還沒被普遍支持,但我已經火燒眉毛了!
這是一篇關於 fetch
的介紹。想了解更多的話請移步到Introduction to Fetch。若是你想找 polyfill
的方案,能夠看看GitHub's implementation。