关于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。