Fetch
Fetch
新的
- 改善离线体验
- 保持可扩展性
而与jQuery.ajax()
的主要区别在于:
fetch()
方法返回的Promise 对象并不会在HTTP 状态码为404 或者500 的时候自动抛出异常,而需要用户进行手动处理- 默认情况下,
fetch 并不会发送任何的本地的cookie 到服务端,注意,如果服务端依靠Session 进行用户控制的话要默认开启Cookie
请求构建
假设
// Simple response handling
fetch("/some/url")
.then(function (response) {})
.catch(function (err) {
// Error :(
});
// Chaining for more "advanced" handling
fetch("/some/url")
.then(function (response) {
return; //...
})
.then(function (returnedValue) {
// ...
})
.catch(function (err) {
// Error :(
});
Request
Request
对象
method
- 使用的HTTP 动词,GET
,POST
,PUT
,DELETE
,HEAD
url
- 请求地址,URL of the requestheaders
- 关联的Header 对象referrer
- referrermode
- 请求的模式,主要用于跨域设置,cors
,no-cors
,same-origin
credentials
- 是否发送Cookie omit
, same-origin
redirect
- 收到重定向请求之后的操作,follow
,error
,manual
integrity
- 完整性校验cache
- 缓存模式( default
, reload
, no-cache
)
// 构建独立的请求对象
const request = new Request("/users.json", {
method: "POST",
mode: "cors",
redirect: "follow",
headers: new Headers({
"Content-Type": "text/plain",
}),
});
// Now use it!
fetch(request).then(function () {
/* handle response */
});
// 直接作为参数传入到 fetch 函数中
fetch("/users.json", {
method: "POST",
mode: "cors",
redirect: "follow",
headers: new Headers({
"Content-Type": "text/plain",
}),
}).then(function () {
/* handle response */
});
在
fetch("/users", {
method: "post",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Hubot",
login: "hubot",
}),
});
URI Encode
注意,
[GET] http://api.com?requestData={"p":"q"}
那么
[GET] http://api.com?requestData={%22p%22:%22q%22}
请求在传入某些后端服务器时可能会触发异常,建议对
//将 requestData 序列化为 JSON
const requestDataString = encodeURIComponent(
JSON.stringify(requestData).replace(/%22/g, '"')
);
//将字符串链接
const packagedRequestURL = `${Model.BASE_URL}${path}?requestData=${requestDataString}&action=${action}`;
Headers | 自定义请求头
// Create an empty Headers instance
const headers = new Headers();
// Add a few headers
headers.append("Content-Type", "text/plain");
headers.append("X-My-Custom-Header", "CustomValue");
// Check, get, and set header values
headers.has("Content-Type"); // true
headers.get("Content-Type"); // "text/plain"
headers.set("Content-Type", "application/json");
// Delete a header
headers.delete("X-My-Custom-Header");
// Add initial values
const headers = new Headers({
"Content-Type": "text/plain",
"X-My-Custom-Header": "CustomValue",
});
常见的请求方法有append
has
get
set
以及 delete
const request = new Request("/some-url", {
headers: new Headers({
"Content-Type": "text/plain",
}),
});
fetch(request).then(function () {
/* handle response */
});
Cookies
如果需要设置same-origin
fetch("/users", {
credentials: "same-origin",
});
该选项会以类似于credentials
的值设置为include
来在
fetch("https://example.com:1234/users", {
credentials: "include",
});
另外需要注意的是,当你为了配置在*
,必须设置为某个具体的域名
Response | 响应处理
在then
函数中提供了一个Response
对象,即代表着对于服务端返回值的封装,你也可以在Response
中,你可以作如下配置
type
-basic
,cors
url
useFinalURL
- 是否为最终地址status
- 状态码(ex: 200
, 404
, etc.) ok
- 是否成功响应(status in the range 200-299) statusText
- status code (ex:OK
)headers
- 响应头
// Create your own response for service worker testing
// new Response(BODY, OPTIONS)
const response = new Response(".....", {
ok: false,
status: 404,
url: "/",
});
// The fetch's `then` gets a Response instance back
fetch("/").then(function (responseObj) {
console.log("status: ", responseObj.status);
});
Response
还提供以下方法:
clone()
- 创建一个Response 对象的克隆。error()
- 返回与网络错误关联的新Response 对象。redirect()
- 使用不同的URL 创建一个新的响应。arrayBuffer()
- 返回一个用ArrayBuffer 解析的promise 。blob()
- 返回一个用Blob 解析的promise 。formData()
- 返回一个用FormData 对象解析的promise 。json()
- 返回一个用JSON 对象解析的promise 。text()
- 返回一个用USVString (text)解析的promise 。
Handling HTTP error statuses | 处理HTTP 错误状态
function checkStatus(response) {
if (response.status >= 200 && response.status < 300) {
return response;
} else {
const error = new Error(response.statusText);
error.response = response;
throw error;
}
}
function parseJSON(response) {
return response.json();
}
fetch("/users")
.then(checkStatus)
.then(parseJSON)
.then(function (data) {
console.log("request succeeded with JSON response", data);
})
.catch(function (error) {
console.log("request failed", error);
});
Handling JSON | 处理JSON 响应
fetch("https://davidwalsh.name/demo/arsenal.json")
.then(function (response) {
// Convert to JSON
return response.json();
})
.then(function (j) {
// Yay, `j` is a JavaScript object
console.log(j);
});
Handling Basic Text/HTML Response | 处理文本响应
fetch("/next/page")
.then(function (response) {
return response.text();
})
.then(function (text) {
// <!DOCTYPE ....
console.log(text);
});
Blob Responses | 二进制数据处理
如果你希望通过
fetch("flowers.jpg")
.then(function (response) {
return response.blob();
})
.then(function (imageBlob) {
document.querySelector("img").src = URL.createObjectURL(imageBlob);
});
blob()
方法会接入一个响应流并且一直读入到结束。
自定义封装
可控的Promise
代理
在上面的介绍中会发现,
/**
* @function 通过透明路由,利用get方法与封装好的QueryParams形式发起请求
* @param BASE_URL 请求根URL地址,注意,需要添加http://以及末尾的/,譬如`http://api.com/`
* @param path 请求路径,譬如"path1/path2"
* @param queryParams 请求的查询参数
* @param contentType 请求返回的数据格式
* @param proxyUrl 请求的路由地址
*/
getWithQueryParamsByProxy({BASE_URL=Model.BASE_URL, path="/", queryParams={}, contentType="json", proxyUrl="http://api.proxy.com"}) {
//初始化查询字符串,将BASE_URL以及path进行编码
let queryString = `BASE_URL=${encodeURIComponent(BASE_URL)}&path=${encodeURIComponent(path)}&`;
//根据queryParams构造查询字符串
for (let key in queryParams) {
//拼接查询字符串
queryString += `${key}=${encodeURIComponent(queryParams[key])}&`;
}
//将查询字符串进行编码
let encodedQueryString = (queryString);
//封装最终待请求的字符串
const packagedRequestURL = `${proxyUrl}?${encodedQueryString}action=GET`;
//以CORS方式发起请求
return this._fetchWithCORS(packagedRequestURL, contentType);
}