前言
Fetch API是新的ajax解决方案,用于解决古老的XHR对象不能实现的问题。
主要优点:
- 语法简单,更加语义化
- 基于标准的Promises实现,支持async/await
本文注意事项:
- 本文假设你已经学习过Promises和async/await,如果没有,请参看我对Promises的理解和异步编程终极大法async/await入门。
- 本文假设你已经通过搜索引擎阅读过一点关于Fetch API的知识,并且试图讲一些别人不常讲的。
适用浏览器
可见,浏览器的支持并不好,可以说相当不好,不过你可以使用各种垫片(polyfill)来实现Fetch API,具体可以搜索一下fetch api polyfill
。不过,我建议:
- 如果你可以保证你项目的用户都在使用现代浏览器,那么你可以直接用Fetch API。
- 如果你的项目还要兼容IE8,那么趁早直接用jQuery,省心。
- 如果只需要兼容IE9以上,还有Axios可以让你选择。
- 当然,你随时可以选择用垫片。
最简单典型的用法
本文假设一个服务器环境,有一个1.html和一个1.php。
fetch('1.php')
.then(function(res) {
res.json().then(function(data) {
console.log(data);
});
})
.catch(function(err) {
console.log('Fetch Error : %S', err);
})
Fetch API跟Promises的关系
console.log(fetch('1.php')); // 返回一个Promise对象
两者关系就一句话:fetch()本身就返回一个Promise对象。所以,它就可以用Promises的所有方法。
fetch的参数
第一个参数:毫无疑问是要获取资源的URL。
第二个参数:options对象,包括:
-
method
: 请求使用的方法,如GET、``POST。
-
headers
: 请求的头信息,形式为Headers
的对象或包含ByteString
值的对象字面量。 -
body
: 请求的 body 信息:可能是一个Blob
、BufferSource
、FormData
、URLSearchParams
或者USVString
对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息。 -
mode
: 请求的模式,如cors、
no-cors
或者same-origin。
-
credentials
: 请求的 credentials,如omit
、same-origin
或者include
。为了在当前域名内自动发送 cookie , 必须提供这个选项, 从 Chrome 50 开始, 这个属性也可以接受FederatedCredential
实例或是一个PasswordCredential
实例。 -
cache
: 请求的 cache 模式:default
、no-store 、
reload 、
no-cache 、
force-cache
或者only-if-cached 。
-
redirect
: 可用的 redirect 模式:follow
(自动重定向),error
(如果产生重定向将自动终止并且抛出一个错误), 或者manual
(手动处理重定向). 在Chrome中,Chrome 47之前的默认值是 follow,从 Chrome 47开始是 manual。 -
referrer
: 一个USVString
,可以是no-referrer
、client
或一个URL。默认是client
。 -
referrerPolicy
: Specifies the value of the referer HTTP header. May be one ofno-referrer、
no-referrer-when-downgrade、
origin、
origin-when-cross-origin、
unsafe-url 。
-
integrity
: 包括请求的 subresource integrity 值 ( 例如:sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=
)。
上面诸多option中,其实常用的就是method
、headers
、body
以及mode
等。
headers
可以为Headers对象,也可以是一个对象字面量,通常情况下对象字面量就足够。
按下F12,查看Network,查看某个请求,可以看到请求头的内容,比如:
Accept:*/*
Accept-Encoding:gzip, deflate, br
Accept-Language:zh-CN,zh;q=0.9
Connection:keep-alive
Content-Length:208
Content-Type:application/x-www-form-urlencoded; charset=UTF-8
......
设置请求头的伪代码例子:
var url = 'http://......';
var headers = {
Accept: 'image/jpeg'
};
fetch(url, {headers: headers}).then(function () {
// ...
})
body
也就是请求体,从上文可以看到,支持的请求体格式非常多,也支持文件上传。可以把文件转为blob,也可以把文件添加到FormData对象中,然后上传。
mode
-
same-origin
表示必须同源,绝对禁止跨域,这个是老版本浏览器默认的安全策略。
fetch('1.php', {
mode: 'same-origin'
}).then(function (response) {
console.log(response);
});
-
cors
表示允许跨域,顾名思义它是以CORS的形式跨域;当然该模式也可以同域请求。只需要服务器的响应头中带有Access-Control-Allow-Origin: *
就行。
fetch('http://外域/1.php', {
mode: 'cors'
}).then(function (response) {
console.log(response);
});
-
no-cors
这个就很特殊了,字面意思是禁止以CORS的形式跨域,其实它的效果是,对外域的请求可以发送,外域服务器无论设不设Access-Control-Allow-Origin: *
都会接收请求并处理请求,但是浏览器不接收响应,即使外域返回了内容,浏览器也当做没接到。
这个no-cors
的用途是保证数据安全。
fetch('http://外域.com/1.php', {
mode: 'no-cors'
}).then(function (response) {
console.log(response);
});
Response
从上面截图可以看到,传给then的回调函数可以接收一个参数,这个参数就是Response,它的属性基本上是只读属性。
上图中看不到的是Response的方法,它的方法如下:
Response.clone()
创建一个Response对象的克隆
Response.error()
返回一个绑定了网络错误的新的Response对象
Response.redirect()
用另一个URL创建一个新的 response.
Response.arrayBuffer()
读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为ArrayBuffer格式的promise对象
Response.blob()
读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为Blob格式的promise对象
Response.formData()
读取Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为FormData格式的promise对象
Response.json()
读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为JSON格式的promise对象
Response.text()
读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为USVString格式的promise对象