AJAX半遮半掩的底层API是饱受诟病的一件事情. XMLHttpRequest 并不是专为Ajax而设计的. 虽然各种框架对 XHR 的封装已经足够好用, 但我们可以做得更好。
window.fetch
方法, 在最新版的 Firefox 和 Chrome 中已经提供支持。1.语法简洁,更加语义化
2.基于标准 Promise 实现,支持 async/await
3.同构方便,使用 isomorphic-fetch
// url (必须), options (可选) fetch('/some/url', { method: 'get' }).then(function(response) { }).catch(function(err) { //中途任何地方出错...在此处理 :( }); //使用 ES6 的 箭头函数 后: fetch(url).then(response => response.json()) .then(data => console.log(data)) .catch(e => console.log("Oops, error", e))
fetch API 也使用了 JavaScript Promises 来处理结果/回调。自定义请求头信息极大地增强了请求的灵活性。我们可以通过
new Headers()
来创建请求头// 创建一个空的 Headers 对象,注意是Headers,不是Header var headers = new Headers(); // 添加(append)请求头信息 headers.append('Content-Type', 'text/plain'); headers.append('X-My-Custom-Header', 'CustomValue'); // 判断(has), 获取(get), 以及修改(set)请求头的值 headers.has('Content-Type'); // true headers.get('Content-Type'); // "text/plain" headers.set('Content-Type', 'application/json'); // 删除某条请求头信息(a header) headers.delete('X-My-Custom-Header'); // 创建对象时设置初始化信息 var headers = new Headers({ 'Content-Type': 'text/plain', 'X-My-Custom-Header': 'CustomValue' })
Request 对象表示一次 fetch 调用的请求信息。传入 Request 参数来调用 fetch, 可以执行很多自定义请求的高级用法:
method
- 支持GET
,POST
,PUT
,DELETE
,HEAD
url
- 请求的 URLheaders
- 对应的Headers
对象referrer
- 请求的 referrer 信息mode
- 可以设置cors
,no-cors
,same-origin
credentials
- 设置 cookies 是否随请求一起发送。可以设置:omit
,same-origin
redirect
-follow
,error
,manual
integrity
- subresource 完整性值(integrity value)cache
- 设置 cache 模式 (default
,reload
,no-cache
)
Request
的示例如下:
var request = new Request('/users.json', { method: 'POST', mode: 'cors', redirect: 'follow', headers: new Headers({ 'Content-Type': 'text/plain' }) }); // 使用! fetch(request).then(function() { /* handle response */ });
只有第一个参数 URL 是必需的。在 Request
对象创建完成之后, 所有的属性都变为只读属性. 请注意, Request
有一个很重要的 clone
方法, 特别是在 Service Worker API 中使用时 —— 一个 Request 就代表一串流(stream), 如果想要传递给另一个 fetch
方法,则需要进行克隆。因为 Request 和 fetch 的签名一致, 所以在 Service Workers 中, 你可能会更喜欢使用 Request 对象。
Response 代表响应, fetch 的 then
方法接收一个 Response
实例, 当然你也可以手动创建 Response
对象
可以配置的参数包括:
type
- 类型,支持:basic
,cors
url
useFinalURL
- Boolean 值, 代表url
是否是最终 URLstatus
- 状态码 (例如:200
,404
, 等等)ok
- Boolean值,代表成功响应(status 值在 200-299 之间)statusText
- 状态值(例如:OK
)headers
- 与响应相关联的 Headers 对象
Response
提供的方法如下:
clone()
- 创建一个新的 Response 克隆对象.error()
- 返回一个新的,与网络错误相关的 Response 对象.redirect()
- 重定向,使用新的 URL 创建新的 response 对象..arrayBuffer()
- Returns a promise that resolves with an ArrayBuffer.blob()
- 返回一个 promise, resolves 是一个 Blob.formData()
- 返回一个 promise, resolves 是一个 FormData 对象.json()
- 返回一个 promise, resolves 是一个 JSON 对象.text()
- 返回一个 promise, resolves 是一个 USVString (text).
1.JSON格式
fetch('http://jartto.wang/test.json') .then(function(response) { // Convert to JSON return response.json(); }) .then(function(result) { console.log(result); });
2.返回HTML/text
fetch('/next/page') .then(function(response) { return response.text(); }).then(function(text) { // <!DOCTYPE .... console.log(text); });
3.发送form表单数据
//form data var form = document.querySelector('form'); fetch('http://jartto.wang/submit', { method: 'post', body: new FormData(form) }); //JSON fetch('http://jartto.wang/submit-json', { method: 'post', body: JSON.stringify({ name: 'jartto', blog: 'http://jartto.wang' }) });
4.图片的处理
fetch('http://jartto.wang/logo.png') .then(function(response) { return response.blob(); }) .then(function(imageBlob) { document.querySelector('img').src = URL.createObjectURL(imageBlob); });
缺点
1.不可以取消:Ajax调用XMLHttpRequest对象上的abort方法,但是Fetch好像没啥办法。
2.浏览器支持:浏览器支持不是很好,但是我们可以用window.fetch polyfill来处理兼容问题。浏览器支持情况大致如下:
- Chrome
- Firefox
- Safari 6.1+
- Internet Explorer 10+
最近把阿里一个千万级 PV 的数据产品全部由 jQuery 的
$.ajax
迁移到 Fetch
,上线一个多月以来运行非常稳定。结果证明,对于 IE8+ 以上浏览器,在生产环境使用 Fetch 是可行的。参考: