[译]还在用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

相关文章
相关标签/搜索