fetch请求详解
最新更新时间:2019年06月04日16:18:30
《猛戳-查看我的博客地图-总有你意想不到的惊喜》
本文内容:fetch相关
概述
位于 WorkerOrGlobalScope 这一个 mixin 中的 fetch() 方法用于发起获取资源的请求。它返回一个 promise,这个 promise 会在请求响应后被 resolve,并传回 Response 对象。
Window 和 WorkerGlobalScope 都实现了 WorkerOrGlobalScope。 ——这意味着基本在任何场景下只要你想获取资源,都可以使用 位于 WorkerOrGlobalScope 中的 fetch() 方法。
Fetch API 提供了一个获取资源的接口(包括跨域请求),Fetch 是对 HTTP 接口的抽象,包括 Request,Response,Headers,Body。得益于 JavaScript 实现的这些抽象好的 HTTP 模块,其他接口能够很方便的使用这些功能。
Fetch 提供了对 Request 和 Response (以及其他与网络请求有关的)对象的通用定义。它同时还为有关联性的概念,例如CORS和HTTP原生头信息,提供一种新的定义,取代它们原来那种分离的定义。
fetch规范与jQuery.ajax()的两个不同点
当接收到一个代表错误的 HTTP 状态码时,从 fetch()返回的 Promise 不会被标记为 reject, 即使该 HTTP 响应的状态码是 404 或 500。相反,它会将 Promise 状态标记为 resolve (但是会将 resolve 的返回值的 ok 属性设置为 false ),仅当网络故障时或请求被阻止时,才会标记为 reject。
默认情况下,fetch 不会从服务端发送或接收任何 cookies, 如果站点依赖于用户 session,则会导致未经认证的请求(要发送 cookies,必须设置 credentials 选项)。自从2017年8月25日后,默认的credentials政策变更为same-originFirefox也在61.0b13中改变默认值
兼容性方案
if(window.fetch) {
// run my fetch request here
} else {
// do something with XMLHttpRequest?
}
语法
//input 必填
//[, init] 选填
Promise<Response> fetch(input[, init]);
input 定义要获取的资源,可以是两种形式,如下简单请求的两种形式:url字符串 / Request对象
可选的配置项对象,包括所有对请求的设置。可选的参数有:
method, headers, body, mode, credentials, cache, redirect, referer, referrerPolicy, integerity
简单的请求
//第一种形式
let url = 'http://www.wanshaobo.com/1.jpg';//必传
let options = {
body: JSON.stringify(data),
headers: new Headers({
'Content-Type': 'application/json',//发送数据方式为json
//'Content-Type': 'application/x-www-form-urlencoded',//发送数据方式为表单提交
}),
method: 'POST',
cache: "default",//default, reload, no-cache
credentials: 'same-origin',//omit 不携带 same-origin 同源请求携带 include 无论跨域还是同源请求都会携带
mode: 'cors'//cors, no-cors, same-origin, navigate
};//可选
fetch(url, options).then(function(Response){
//fetch方法创建的Promise对象 返回resolved状态的回调函数
//Response对象详解见下表
},function(error){
//fetch方法创建的Promise对象 返回rejected状态的回调函数
})
//第二种形式
let Request = new Request(url, { method: 'POST', body: '{"foo":"bar"}'});
fetch(Request).then(function(Response){
//fetch方法创建的Promise对象 返回resolved状态的回调函数
//Response对象详解见下表
},function(error){
//fetch方法创建的Promise对象 返回rejected状态的回调函数
})
- 属性
key | value | type |
---|---|---|
Response.headers | 包含此Response所关联的Headers 对象 | 只读 |
Response.ok | 包含了一个布尔值来标示该 Response 成功(状态码的范围在200-299) | 只读 |
Response.redirected | 表示该Response是否来自一个重定向,如果是的话,它的URL列表将会有多个entry | 只读 |
Response.status | 包含Response的状态码 | 只读 |
Response.statusText | 包含了与该Response状态码一致的状态信息 (例如, OK对应 200) | 只读 |
Response.type | 包含Response的类型 (例如, basic, cors) | 只读 |
Response.url | 包含Response的URL | 只读 |
Response.useFinalURL | 包含了一个布尔值来标示这是否是该Response的最终URL | - |
Response.headers | 包含此Response所关联的Headers 对象 | 只读 |
Response.headers | 包含此Response所关联的Headers 对象 | 只读 |
- 方法
key | value | type |
---|---|---|
Response.json() | 读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为JSON格式的promise对象。 | |
Response.text() | 读取 Response对象并且将它设置为已读(因为Responses对象被设置为了 stream 的方式,所以它们只能被读取一次) ,并返回一个被解析为USVString格式的promise对象。 |
图片的请求demo
//形式一
var myImage = document.querySelector('img');
var myRequest = new Request('flowers.jpg');
fetch(myRequest).then(function(response) {
return response.blob();
}).then(function(response) {
var objectURL = URL.createObjectURL(response);
myImage.src = objectURL;
});
//形式二
var myImage = document.querySelector('img');
var myHeaders = new Headers();
myHeaders.append('Content-Type', 'image/jpeg');
var init = { method: 'GET', headers: myHeaders, mode: 'cors', cache: 'default' };
var myRequest = new Request('flowers.jpg');
fetch(myRequest,init).then(function(response) {
...
});
//形式三
var myRequest = new Request('flowers.jpg',myInit);
var init = {
method: 'GET',
headers: { 'Content-Type': 'image/jpeg' },
mode: 'cors',
cache: 'default'
};
var myRequest = new Request('flowers.jpg', init);
fetch(myRequest).then(function(response) {
...
});
完整的应用方案一
没有对fetch进行Promise包装,login方法的then回调是Response.json()返回的Promise实例
优点:代码简洁
缺点:不能在request方法体中做全局的res.code状态码统一处理,只能在login方法的then回调中做每一个请求的单独处理
//实际的方法调用
let requestData = { }
login(requestData).then(res => {
console.log('/abc 接口的返回值',res);// JSON from `response.json()` call
}).catch(e => {
console.log(e);
})
//业务的方法
function login(obj) { //登录
return request('/abc',obj)
}
//fetch的包装
function request(url,data) {
return fetch(baseURL + url, {
body: JSON.stringify(data),
headers: new Headers({ 'Content-Type': 'application/json'}),
method: 'POST',
cache: "default",
credentials: 'include',//'same-origin' 'include'
}).then(Response => Response.json(),err => { }).catch((e)=>{ })
}
完整的应用方案二
对fetch进行Promise包装,在request方法体中做全局的res.code状态码统一处理,login方法的then回调是包装的Promise的返回值。
//实际的方法调用
let requestData = { }
login(requestData).then(res => {
//Promise对象resolved
console.log('/abc 接口的返回值',res.data);
},err => {
//Promise对象rejecetd
console.log(err)
}).catch(e => {
//catch方法处理 Promise 内部发生的错误,捕获两种错误:
//1、then方法指定的两个回调函数,如果运行中抛出错误,会被catch方法捕获;
//2、rejected状态也会被catch方法捕获
//catch方法返回的还是一个 Promise 对象
console.log(e);
})
//业务的方法
function login(obj) { //登录
return request('/abc',obj)
}
//fetch的包装
import { message} from "antd";
import { createBrowserHistory } from 'history';
const history = createBrowserHistory();
function request(url,data) {
return new Promise((resolve,reject)=>{
fetch(baseURL + url, {
body: JSON.stringify(data),
headers: new Headers({ 'Content-Type': 'application/json'}),
method: 'POST',
cache: "default",
credentials: 'same-origin'
}).then((Response)=>{
//fetch请求返回resolved状态的回调函数
let data = Response.json()//res是一个json文件,使用 json() 读取并解析数据,返回一个被解析为JSON格式的promise对象
data.then((res,rej)=>{
if(res.code == 100){
resolve(res)
}else if(res.code == 11115){
//用户登录失效,token失效,跳转到登录页面
history.replace('/login')
}else{
message.destroy()
message.error(res.message);
}
})
},err => {
//fetch请求返回rejected状态的回调函数
//fetch请求 网络故障时或请求被阻止时,标记为 reject
reject(err)
}).catch((e)=>{
reject(e)
})
})
}
完整的应用方案三:FormData() 和fetch()上传文件
body使用FromData对象,主要用于序列化表单以及创建与表单格式相同的数据
通过HTML元素,FormData() 和fetch()上传文件。
var formData = new FormData();
var fileField = document.querySelector("input[type='file']");
formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);
function request(url,data) {
return new Promise((resolve,reject)=>{
fetch(url, {
body: formData,
method: 'PUT',
}).then((Response)=>{
let data = Response.json()
data.then((res,rej)=>{
})
})
})
}
完整的应用方案四:FormData() 和fetch()上传多个文件
可以通过HTML元素,FormData() 和fetch()上传文件。
var formData = new FormData();
var photos = document.querySelector("input[type='file'][multiple]");
formData.append('title', 'My Vegas Vacation');
formData.append('photos', photos.files);
function request(url,data) {
return new Promise((resolve,reject)=>{
fetch(url, {
body: formData,
method: 'PUT',
}).then((Response)=>{
let data = Response.json()
data.then((res,rej)=>{
})
})
})
}
参考资料
- Fetch API - Web API
- 使用 Fetch - Web API
- WorkerOrGlobalScope.fetch() - Web API
- Request - Web API
- Response - Web API
- Headers - Web API
- Body - Web API
感谢阅读,欢迎评论^-^
还没有评论,来说两句吧...