概况
JavaScript 通过 XMLHttpRequest(XHR) 来执行异步请求,这个方式已经存在了很长一段时间。但它不是最佳API。它在设计上不符合职责分离原则,将输入、输出和用事件来跟踪的状态混杂在一个对象里。而且,基于事件的模型与最近 JavaScript 流行的 Promise 以及基于生成器的异步编程模型不太搭。新的 Fetch API 打算修正上面提到的那些缺陷。
而与jQuery相比, fetch 方法与 jQuery.ajax() 的主要区别在于:
fetch()方法返回的Promise对象并不会在HTTP状态码为404或者500的时候自动抛出异常,而需要用户进行手动处理- 默认情况下,
fetch并不会发送任何的本地的cookie到服务端,注意,如果服务端依靠Session进行用户控制的话要默认开启Cookie
Installation & Polyfill
window.fetch 是基于 XMLHttpRequest 的浏览器的统一的封装,针对老的浏览器可以使用 Github 的这个polypill。 fetch 基于 ES6 的 Promise ,在旧的浏览器中首先需要引入 Promise的 polypill ,可以用 es6-promise:1
npm install es6-promise
使用 isomorphic-fetch:1
npm install --save isomorphic-fetch es6-promise
使用的时候也非常方便:
1 | require('es6-promise').polyfill(); |
Usage
HTML
1 | fetch('/users.html') |
JSON
1 | fetch('/users.json') |
Response metadata
1 | fetch('/users.json').then(function(response) { |
Post form
1 | var form = document.querySelector('form') |
Post JSON
1 | fetch('/users', { |
File upload
1 | var input = document.querySelector('input[type="file"]') |
Request:请求构造
Request对象代表了一次fetch请求中的请求体部分,你可以自定义Request对象:
method- 使用的HTTP动词,GET,POST,PUT,DELETE,HEADurl- 请求地址,URL of the requestheaders- 关联的Header对象referrer-referrermode- 请求的模式,主要用于跨域设置,cors,no-cors,same-origincredentials- 是否发送Cookieomit,same-originredirect- 收到重定向请求之后的操作,follow,error,manualintegrity- 完整性校验cache- 缓存模式(default,reload,no-cache)1
2
3
4
5
6
7
8
9
10
11var request = new Request('/users.json', {
method: 'POST',
mode: 'cors',
redirect: 'follow',
headers: new Headers({
'Content-Type': 'text/plain'
})
});
//use it
fetch(request).then(function() { /* handle response */ });
1 | fetch('/users.json', { |
Cookies
如果需要设置fetch自动地发送本地的Cookie,需要将credentials设置为same-origin:1
2
3fetch('/users', {
credentials: 'same-origin'
})
该选项会以类似于XMLHttpRequest的方式来处理Cookie,否则,可能因为没有发送Cookie而导致基于Session的认证出错。可以将credentials的值设置为include来在CORS情况下发送请求。1
2
3fetch('https://example.com:1234/users', {
credentials: 'include'
})
Headers:自定义请求头
1 | // Create an empty Headers instance |
使用webpack前后端跨域发送cookie的问题
最简单的方法是服务端将响就头设置成 Access-Control-Allow-Origin:域名,如果客户端发送请求时,不需要携带 cookie 等信息,可以设置成 Access-Control-Allow-Origin:* ,表示任何域都可以向服务端发送请求,客户端不需要任何配置,就可以进行跨域调试了。
但一般网站,都需要向后端发送 cookie来进行身份验证,此时,服务器还需向响应头设置 Access-Control-Allow-Credentials:true,表示跨域时,允许cookie添加到请求中。设置 Access-Control-Allow-Credentials:true 后,要将 Access-Control-Allow-Origin 指定到具体的域,否则cookie不会带到客户端,例如设置成Access-Control-Allow-Origin:http://192.168.0.1:8088,http://192.168.0.1:8088 是前端服务器的域名,这就要求用webpack的时候,要指定具体的域来启动,不要直接用localhost。1
2
3
4
5...
devServer: {
host: '192.168.0.1:8088',
},
...
要向后端发送cookie,前端也需要有相应的配置。需要将credentials设置成include,表示允许跨越传递cookie,不要将credentials设置成same-origin,如果设置成same-origin,只会在同源的时候发送cookie。另外还要将 withCredentials 设为true。
Response:响应处理
在fetch的then函数中提供了一个Response对象,即代表着对于服务端返回值的封装,你也可以在Mock的时候自定义Response对象,譬如在你需要使用Service Workers的情况下,在Response中,你可以作如下配置:
type- basic, corsurluseFinalURL- 是否为最终地址status- 状态码 (ex: 200, 404, etc.)ok- 是否成功响应 (status in the range 200-299)statusText- status code (ex: OK)headers- 响应头
The Response also provides the following methods:
clone()- Creates a clone of a Response object.error()- Returns a new Response object associated with a network error.redirect()- Creates a new response with a different URL.arrayBuffer()- Returns a promise that resolves with an ArrayBuffer.blob()- Returns a promise that resolves with a Blob.formData()- Returns a promise that resolves with a FormData object.json()- Returns a promise that resolves with a JSON object.text()- Returns a promise that resolves with a USVString (text).
处理HTTP错误状态
1 | function checkStatus(response) { |
处理JSON响应
1 | fetch('https://davidwalsh.name/demo/arsenal.json').then(function(response) { |
处理文本响应
1 | fetch('/next/page') |
Blob Responses
如果你希望通过fetch方法来载入一些类似于图片等资源:
1 | fetch('flowers.jpg') |






