[譯]還在用XMLHttpRequest來作AJAX?試試Fetch吧!

關於ajax,一我的盡皆知的祕密是,它的基礎API:XMLHttpRequest,用它來作ajax請求實在是不太合適。咱們已經在創造一個優雅的,關於xhr的一些API上作得很好了,可是咱們能作得更好,而能讓咱們作得更好的就是使用fetch API!下面咱們一塊兒簡單地看看這個新增的window.fetch方法,目前已經能夠在Firefox和Chrome Canary上使用了。(注:如今已經能夠在最新的Chrome穩定版本上使用)javascript

XMLHttpRequest

在我看來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

基本的Fetch用法

在全局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,setdelete方法去更改請求頭。能夠經過建立一個請求實例去使用這個請求頭。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

一個 Request 實例表明着一個 fetch 方法調用的片斷。經過交給 fetch 一個 Request對象你能夠建立一個高級的、定製的請求:緩存

  • method - GET, POST, PUT, DELETE, HEAD
  • url - 請求的url
  • headers - 和Headers對象有關
  • referrer - 請求的referrer
  • mode - cors, no-cors, same-origin幾個模式
  • credentials - 設置cookie是否隨請求一塊兒發送,固然了,有同源策略
  • redirect - follow, error, manual
  • integrity - SRI的值
  • cache - 緩存模式 (default, reload, no-cache)

一個簡單的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實例,由於Requestfetch的用法能夠說是同樣的。

Response

fetchthen方法提供了一個Response實例,但你能夠手動建立一個Response對象——一種你可能會在使用service workers時遇到的狀況。你能夠這樣設置Response:

  • type - basic, cors
  • url
  • useFinalURL - Boolean值,說明url是否是最後的URL
  • status - 狀態碼 (好比: 200, 404。。。)
  • ok - Boolean 值,是否成功響應 (200到299間的狀態)
  • statusText - 狀態碼的文字描述 (好比: OK)
  • headers - 和response 關聯的Headers 對象
// 建立你本身的響應,以測試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 對象也提供了這些方法:

  • clone() - 建立一個Response對象的拷貝
  • error() - 返回一個新的關於網絡錯誤的Response對象
  • redirect() - 建立一個新的不一樣url的響應
  • arrayBuffer() - 返回一個promise,一個攜帶ArrayBuffer的resolve
  • blob() - 返回一個promise,一個攜帶Blob的resolve
  • formData() - 返回一個返回一個promise,一個攜帶formData對象的resolve
  • json() - 返回一個返回一個promise對象,一個攜帶json的resolve
  • text() - 返回一個返回一個promise對象,一個攜帶USVString(text)的resolve

處理JSON

當你建立了一個請求,而請求的是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方法是一條方便的捷徑。

處理基本的文本/HTML響應

JSON 不會一直是咱們指望的響應格式,因此這邊你能夠看看怎麼處理文本或者HTML響應。

fetch('/next/page')
  .then(function(response) {
    return response.text();
  }).then(function(text) { 
  	// <!DOCTYPE ....
  	console.log(text); 
  });
複製代碼

你能夠經過在text()方法後連接上Promise的 then 方法來得到響應文本。

處理Blob響應

若是你想經過 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流並將其讀取完成。

發送From Data

另一個一般會使用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

原文連接:davidwalsh.name/fetch

相關文章
相關標籤/搜索