文章目录
01 fetch
必须开启服务器
JavaScript 通过 XMLHttpRequest(XHR)
来执行异步请求,这个方式已经存在了很长一段时间。虽说它很有用,但它不是最佳 API。它在设计上不符合职责分离原则,将输入、输出和用事件来跟踪的状态混杂在一个对象里
Fetch API 提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的部分,例如请求和响应。它还提供了一个全局 fetch()
方法,该方法提供了一种简单,合乎逻辑的方式来跨网络异步获取资源
1.1 fetch 规范与 jQuery.ajax() 两种方式的不同
从 fetch()
返回的 Promise 将不会拒绝 HTTP 错误状态,即使响应是一个 HTTP 404 或 500。相反,它会正常解决(其中 ok 状态设置为 false),并且仅在网络故障时或任何阻止请求完成时,它才会拒绝
默认情况下,fetch 在服务端不会发送或接收任何 cookies,如果站点依赖于维护一个用户会话,则导致未经认证的请求(要发送 cookies,必须发送凭据头)
1.2 Promise
所谓 Promise,就是一个对象,用来传递异步操作的消息
Promise 对象有以下两个特点
- 对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和 Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态
- 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise 对象的状态改变,只有两种可能:从 Pending 变为 Resolved 和从 Pending 变为 Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。就算改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的
1.3 Fetch API 的支持情况
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>demo01</title>
</head>
<body>
<button id="btn"></button>
<script>
var btn = document.getElementById('btn');
btn.onclick = fetchFun;
function fetchFun(){
if(window.fetch){
console.log('use fetch');
}else{
console.log('use ajax');
}
}
</script>
</body>
</html>
1.4 发起 fetch 请求
在 Fetch API 中,最常用的就是 fetch()
函数,它接收一个 URL 参数,返回一个 promise 来处理 response。response 参数带着一个 Response 对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>demo01</title>
</head>
<body>
<button id="btn">click</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = fetchFun;
function fetchFun(){
if(window.fetch){
fetch('./fetch.txt').then(function (response){
return response.json().then(function (data){
// 相当于ajax里成功的回调函数
console.log(data);
})
})
}else{
console.log('use ajax');
}
}
</script>
</body>
</html>
1.5 request
Request 接口定义了通过 HTTP 请求资源的 request 格式。参数需要 URL、method 和 headers,同时 Request 也接受一个特定的 body、mode、credentials 以及 cache hints
-
mode 属性:用来决定是否允许跨域请求,以及哪些 response 属性可读
- same-origin:所有的请求遵守同源策略。如果请求是跨域的,那么返回一个简单的 error
- no-cors:允许来自 CDN 的脚本、其他域的图片和其他一些跨域资源,但是首先有个前提条件,就是请求的 method 只能是 “HEAD”、“GET” 或者 “POST”
- cors:通常用作跨域请求来从第三方提供的 API 获取数据。只有有限的一些 headers 被暴露给Response 对象,但是 body 是可读的
-
credentials 枚举属性:决定了 cookies 是否能跨域得到。这个属性与 XHR 的 withCredentials 标志相同,但是只有三个值,分别是 “omit”(默认)、“same-origin” 以及 “include”
-
caching hints 。Request 对象也可以提供 caching hints 给用户代理。这个属性还在安全复审阶段。Firefox 提供了这个属性,但是它目前还不起作用
1.6 自定义请求的参数
fetch()
接受第二个可选参数,一个可以控制不同配置的 init 对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>demo01</title>
</head>
<body>
<button id="btn">click</button>
<script>
var btn = document.getElementById('btn');
btn.onclick = fetchFun;
var myInit = {
method: 'GET',
// headers: myHeaders,
mode: 'cors',
cache: 'default'
};
function fetchFun() {
fetch('./fetch.txt',myInit).then(function (res) {
if(res.ok == true) {
return res.json().then(function (data) {
console.log(data)
});
}else{
console.log('network is no ok', res.status);
}
}), function(e) {
console.log("Fetch failed!", e);
}
}
</script>
</body>
</html>
1.7 Response
Response 中最常见的成员是 status(一个整数默认值是 200)和 statusText(默认值是 “OK”),对应 HTTP 请求的 status 和 reason。还有一个 “ok” 属性,当 status 为 2xx 的时候它是 true
1.8 处理 body
无论 Request 还是 Response 都可能带着 body。由于 body 可以是各种类型,比较复杂,所以前面我们故意先略过它,在这里单独拿出来讲解
body 可以是以下任何一种类型的实例
-
ArrayBuffer
-
ArrayBufferView(Uint8Array and friends)
-
Blob/File
-
字符串
-
URLSearchParams
-
FormData —— 目前不被 Gecko 和 Blink 支持,Firefox 预计在版本 39 和 Fetch 的其他部分一起推出
Request 和 Response 都为他们的 body 提供了以下方法,这些方法都返回一个 Promise 对象
-
arrayBuffer()
-
blob()
-
json()
-
text()
-
formData()
irefox 预计在版本 39 和 Fetch 的其他部分一起推出
Request 和 Response 都为他们的 body 提供了以下方法,这些方法都返回一个 Promise 对象
-
arrayBuffer()
-
blob()
-
json()
-
text()
-
formData()