XMLHttpRequest
XMLHttpRequest优点
1.不重新加载页面的情况下更新网页 2.在页面已加载后从服务器请求/接收数据 3.在后台向服务器发送数据。
XMLHttpRequest缺点
1.使用起来也比较繁琐,需要设置很多值。 2.早期的IE浏览器有自己的实现,这样需要写兼容代码 兼容性查询:caniuse.com/?search=XML…
一、版本区别
XMLHttpRequest Level 1缺点
- 不能发送二进制文件(如图片、视频、音频等),只能发送纯文本数据。
- 在发送和获取数据的过程中,无法实时获取进度信息,只能判断是否完成。
- 受同源策略的限制,不能发送跨域请求。
XMLHttpRequest Level 2新增功能
- 在服务端允许的情况下,可以发送跨域请求。
- 支持发送和接收二进制数据。
- 新增formData对象,支持发送表单数据。
- 发送和获取数据时,可以获取进度信息。
- 可以设置请求的超时时间
二、请求API
1.open()方法:用于初始化一个请求,接收三个参数。
- 第一个参数 method:要发送的请求的类型。比如GET、POST、PUT、DELETE等。
- 第二个参数 url:请求的URL。
- 第三个参数 async:是否异步发送请求的布尔值。true为异步发送请求。
const xhr = new XMLHttpRequest() xhr.open('get', '/userInfo', true)
2.send()方法:发送HTTP请求,接收一个参数data。
data:作为请求主体发送的数据。如果不需要通过请求主体发送数据,则必须传入null。该参数可以接收字符串、FormData、Blob、ArrayBuffer等类型。
const xhr = new XMLHttpRequest() xhr.send(null)
3. setRequestHeader()方法:可以设置自定义的请求头部信息,接收两个参数header:头部字段的名称;value:头部字段的值。
const xhr = new XMLHttpRequest()
xhr.open('get', '/server', true)
// xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.setRequestHeader('MyHeader', 'MyValue')
xmlhttp.send()
注:要成功发送请求头部信息,此方法必须在open()和send()之间调用
4.readyState属性和onreadystatechange事件
readyState表示请求/响应过程的当前活动阶段。属性值如下:
- 0(UNSENT)未初始化。尚未调用open()方法。
- 1(OPENED)启动。已经调用open()方法,但没有调用send()方法。
- 2(HEADERS_RECEIVED)发送。已经调用send()方法,但尚未接收到响应。
- 3(LOADING)接收。已经接收到部分响应数据。
- 4(DONE)完成。已经接收到全部响应数据。
只要readyState属性的值发生变化,都会触发一次onreadystatechange事件。利用这个事件来检测每次状态变化后readyState的值。一般情况下只对readyState值为4的阶段做处理,此时所有数据都已经就绪。
const xhr = new XMLHttpRequest()
xhr.open('get', '/server', true)
xhr.onreadystatechange = function () {
if(xhr.readyState !== 4) {
return
}
if(xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.responseText)
}
}
xhr.send(null)
5.timeout属性和ontimeout事件
Timeout:表示请求在等待响应多少毫秒之后就终止。如果在规定的时间内浏览器还没有接收到响应,就会触发ontimeout事件处理程序。
const xhr = new XMLHttpRequest()
xhr.open('get', '/server', true)
//将超时设置为3秒钟
xhr.timeout = 3000
// 请求超时后请求自动终止,会调用 ontimeout 事件处理程序
xhr.ontimeout = function(){
console.log('请求超时了')
}
xhr.send(null)
6.overrideMimeType()方法:能够重写服务器返回的MIME类型,从而让浏览器进行不一样的处理。
假如服务器返回的数据类型是text/xml,由于种种原因浏览器解析不成功报错,这时就拿不到数据。为了拿到原始数据,我们可以把MIME类型改成text/plain,这样浏览器就不会去自动解析,从而我们就可以拿到原始文本了。
const xhr = new XMLHttpRequest()
xhr.open('get', '/server', true)
xhr.overrideMimeType('text/plain')
xhr.send(null)
7.responseType属性:是一个字符串,告诉服务器返回指定类型的数据。使用xhr.response属性来接收。
调用在open()方法之后,send()方法之前
当将responseType设置为一个特定的类型时,你需要确保服务器所返回的类型和你所设置的返回值类型是兼容的。那么如果两者类型不兼容,服务器返回的数据就会变成null,即使服务器返回了数据。
//获取图片responseType抛出InvalidAccessError的异常示例。
const xhr = new XMLHttpRequest()
xhr.open('get', '/server/image.png', true)
xhr.responseType = 'blob' // 正确使用arraybuffer
xhr.onload = function(e) {
if (xhr.status >= 200 && xhr.status < 300) {
const blob = this.response
// ...
}
}
xhr.send(null)
8.withCredentials属性:是一个布尔值,表示跨域请求时是否协带凭据信息(cookie、HTTP认证及客户端SSL证明等)。默认为false。
如果跨域Ajax请求发送Cookie,withCredentials属性设为true。同域下写不写都一样
const xhr = new XMLHttpRequest()
xhr.open('get', '/server', true)
xhr.withCredentials = true
xhr.send(null)
当配置了withCredentials为true时,须在后端增加response头信息Access-Control-Allow-Origin,且必须指定域名,而不能指定为*。并且添加Access-Control-Allow-Credentials这个头信息为true。
response.addHeader("Access-Control-Allow-Origin", "http://example.com")
response.addHeader("Access-Control-Allow-Credentials", "true")
9.abort()方法和onabort事件
在接收到响应之前调用abort()方法用来取消异步请求。当一个请求被终止后,它的readyState属性将被置为0。在终止请求之后,还应该对XMLHttpRequeat对象进行解引用操作。 当调用abort()后,会触发onabort事件。
const xhr = new XMLHttpRequest()
xhr.open('get', '/server', true)
xmlhttp.onabort = function () {
console.log('请求被中止')
}
xmlhttp.send()
// 将会调用我们上面定义的 onabort 回调函数
xmlhttp.abort()
10.GET请求
将查询字符串参数追加到URL的末尾,将信息发送给服务器。 GET参数的编码方式是无法人为干涉的,这导致了不同浏览器有不同的编码方式,因此最稳妥的方案是人工预编码,人工解码,从而禁止浏览器编码的干涉。
// 使用encodeURIComponent()进行编码
const tempParam = encodeURIComponent('age')
const tempValue = encodeURIComponent('20')
xhr.open('get', '/server?tempParam=tempValue&money=100', true)
11.POST请求:把数据作为请求的主体(请求的body)提交。
常见的POST请求提交数据方式。
-
- application/x-www-form-urlencoded 浏览器的原生form表单,如果不设置enctype属性,那么最终就会以application/x-www-form-urlencoded方式提交数据。
-
- multipart/form-data 表单上传文件时,必须让form表单的enctype等于multipart/form-data。
-
- application/json 当发送Ajax请求时,把application/json作为请求头,用来告诉服务端消息主体是序列化后的JSON字符串。
-
- text/xml
- 使用HTTP作为传输协议,XML作为编码方式的远程调用规范
- 使用XMLHttpRequest模拟表单提交
- 将Content-Type头部信息设置为application/x-www-form-urlencoded
-
- XMLHttpRequest模仿表单提交。
const xhr = new XMLHttpRequest()
xhr.open('post', '/server', true)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
const form = document.getElementById('myForm')
// serialize()为表单序列化方法
xhr.send(serialize(form))
- 6.XMLHttpRequest level 2的FormData来序列化表单数据。
const xhr = new XMLHttpRequest()
xhr.open('post', '/server', true)
const form = document.getElementById('myForm')
const formData = new FormData(form)
formData.append("id", "123456")
xhr.send(formData)
使用FormData不用设置请求头部。XMLHttpRequest对象能够识别传入的数据类型是FormData的实例,并配置适当的头部信息
三、XMLHttpRequest进度事件相关API
1.onloadstart
在XMLHttpRequest对象开始传送数据时被触发,也就是调用send()方法(HTTP 请求发出)的时候。
xhr.onloadstart = function () {
console.log('开始发出请求...')
}
2.onprogress
在接收响应期间持续不断地触发;会接收到一个event对象,它的target属性是XMLHttpRequest对象,并且event包含着三个额外的属性:loaded、total和lengthComputable。
- event.loaded:已传输的数据量(已经接收的字节数)。
- event.total:总共的数据量(根据Content-Length响应头部确定的预期字节数)。
- event.lengthComputable:进度信息是否可用的布尔值。
有了这些信息,就可以创建一个Ajax请求进度条了。
const xhr = new XMLHttpRequest()
xhr.onprogress = function (event) {
if (!event.lengthComputable) {
return console.log('无法计算进展')
}
const percentComplete = event.loaded / event.total * 100
console.log(`进度百分比:${percentComplete}%`)
}
xhr.open('post', '/server', true)
xhr.send(null)
3.onerror
在请求发生错误时触发。只有发生了网络层级别的异常才会触发此事件,对于应用层级别的异常,比如响应返回的statusCode是4xx时,并不属于NetWork Error,所以不会触发onerror事件,而是会触发onload事件。
xhr.onerror = function(e) {
console.log('数据接收出错')
}
4.onabort
调用abort()方法而终止请求时触发。
5.onload
当请求成功,接收到完整的响应数据时触发,可以用来替代readystatechange事件;只要浏览器接收到服务器的响应,不管其状态如何,都会触发load事件。
const xhr = new XMLHttpRequest()
xhr.onload = function onload() {
console.log('数据接收完毕')
if(xhr.status >= 200 && xhr.status < 300) {
console.log(xhr.responseText)
}
}
xhr.open('post', '/server', true)
xhr.send(formData)
为确保正常执行,必须在调用open()方法之前添加onprogress事件处理程序。
6.onloadend
在请求结束(包括请求成功和请求失败),或者触发error、abort或load事件后触发。
xhr.onloadend = function(e) {
console.log('请求结束,状态未知')
}
每个请求都从触发loadstart事件开始,接下来是一或多个progress事件,然后触发error、 abort或load事件中的一个,最后以触发loadend事件结束。
7.upload
XMLHttpRequest不仅可以发送请求,还可以发送文件,就是Ajax文件上传。 发送文件以后,通过XMLHttpRequest.upload属性可以得到一个XMLHttpRequestUpload对象。通过这个对象,可以得知上传的进展。实现方案就是监听这个对象的各种事件:onloadstart、onprogress、onabort、onerror、onload、ontimeout、onloadend。 当文件上传时,对upload属性指定progress事件的监听函数,可获得上传的进度。
const xhr = new XMLHttpRequest()
if (xhr.upload) {
xhr.upload.onprogress = function progress(e) {
if (e.total > 0) {
e.percent = e.loaded / e.total * 100
}
}
}
四、XMLHttpRequest对象接收响应相关API
1. 响应头相关
- Content-Type:服务器告诉客户端响应内容的类型和采用字符编码。比如:Content-Type: text/html; charset=utf-8。
- Content-Length:服务器告诉客户端响应实体的大小。比如:Content-Length: 8368。
- Content-Encoding:服务器告诉客户端返回的的压缩编码格式。比如:Content-Encoding: gzip, deflate, br。 2.status
返回一个整数,表示服务器回应的HTTP状态码。如果服务器没有返回状态码,那么这个属性默认是200。请求发出之前,该属性为0。该属性只读**。
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// 处理服务器的返回数据
}
}
3.statusText
返回一个只读属性字符串,表示服务器发送的状态说明。比如OK和Not Found。在请求发送之前,该属性的值是空字符串。如果服务器没有返回状态提示,该属性的值默认为OK。**
要通过检测status属性来决定下一步的操作,不要依赖statusText,因为statusText在跨浏览器使用时不太可靠。
4.response
表示服务器返回的只读数据。它可以是任何数据类型,比如字符串、对象、二进制对象等,具体的类型由XMLHttpRequest.responseType属性决定。**
如果本次请求没有成功或者数据不完整,该属性等于null。
const xhr = new XMLHttpRequest()
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
console.log(xhr.response)
}
}
5.responseText
返回从服务器接收到的字符串,该属性为只读。**
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
// 处理服务器的返回数据
console.log(xhr.responseText)
}
}
6.responseXML属性
如果响应的内容类型是"text/xml"或"application/xml",这个属性中将保存包含着响应数据的HTML或XML文档对象。该属性是只读属性。
无论内容类型是什么,响应主体的内容都会保存到responseText属性中。而对于非XML数据而言,responseXML属性的值将为null。
7.responseURL属性
是字符串,表示发送数据的服务器的网址。如果URL为空则返回空字符串。如果URL有锚点,则位于URL#后面的内容会被删除。如果服务器端发生跳转,这个属性返回最后实际返回数据的网址。
const xhr = new XMLHttpRequest()
xhr.open('GET', 'http://example.com/test', true)
xhr.onload = function () {
// 返回 http://example.com/test
console.log(xhr.responseURL)
}
xhr.send(null)
8.getResponseHeader()方法
返回HTTP头信息指定字段的值,如果还没有收到服务器的响应或者指定字段不存在,返回null。该方法的参数不区分大小写。
const xhr = new XMLHttpRequest()
xhr.onload = function onload() {
console.log(xhr.getResponseHeader('Content-Type'))
}
xhr.open('post', '/server', true)
xhr.send(null)
如果有多个字段同名,它们的值会被连接为一个字符串,每个字段之间使用逗号+空格分隔。
9.getAllResponseHeaders()方法
返回一个字符串,表示服务器发来的所有HTTP头信息。格式为字符串,每个头信息之间使用CRLF分隔(回车+换行),如果没有收到服务器回应,该属性为null。如果发生网络错误,该属性为空字符串。
const xhr = new XMLHttpRequest()
xhr.onload = function onload() {
const responseHeaders = 'getAllResponseHeaders' in xhr ? xhr.getResponseHeaders() : null
}
xhr.open('post', '/server', true)
xhr.send(null)
Ajax
兼容性查询:caniuse.com/?search=AJA…
1.创建Ajax核心对象XMLHttpRequest
var xhr=null;
if (window.XMLHttpRequest)
{// 兼容 IE7+, Firefox, Chrome, Opera, Safari
xhr=new XMLHttpRequest();
} else{// 兼容 IE6, IE5
xhr=new ActiveXObject("Microsoft.XMLHTTP");
}
2.向服务器发送请求
xhr.open(method,url,async); // 初始化一个请求,同XHR
send(string);//post请求时才使用字符串参数,否则不用带参数。
//post请求要设置请求头的格式内容
xhr.open("POST","test.html",true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send("fname=Henry&lname=Ford");
3.服务器响应处理
responseText:获得字符串形式的响应数据。
responseXML:获得XML 形式的响应数据。
- 同步处理
xhr.open("GET","info.txt",false);
xhr.send();
//获取数据直接显示在页面上
document.getElementById("myDiv").innerHTML=xhr.responseText;
- 异步处理
xhr.onreadystatechange=function() {
if (xhr.readyState==4 &&xhr.status==200) {
document.getElementById("myDiv").innerHTML=xhr.responseText;
}
}
axios
axios基于promise用于浏览器和nodejs的http客户端,本质上也是对原生XHR的封装,只不过他是promise的实现版本,符合最新ES规范
兼容性查询:caniuse.com/?search=AJA…
axios优点
- 支持浏览器与nodejs前后端发请求
- 支持promise语法,
- 支持自动解析json
- 支持中断请求
- 支持拦截请求
- 支持进度条检测
- 支持客户端防止CSRF
- 提供一些并发请求的接口(重要,方便了很多的操作)
axios缺点
- 低版本浏览器无法使用promise,需要添加polyfill
axios API
axios(config)
//发起 POST请求
axios({
method:'post',//方法
url:'/user/12345',//地址
data:{//参数
firstName:'Fred',
lastName:'Flintstone'
}
});
//通过请求获取远程图片
axios({
method:'get',
url:'http://bit.ly/2mTM3Ny',
responseType:'stream'
}).then(function(response){
response.data.pipe(fs.createWriteStream('ada_lovelace.jpg'))
})
axios(url[,config])
//发起一个GET请求
axios('/user/12345/);
请求方法的别名
- axios.request(config)
- axios.get(url[,config])
- axios.delete(url[,config])
- axios.head(url[,config])
- axios.options(url[,config])
- axios.post(url[,data[,config]])
- axios.put(url[,data[,config]])
- axios.patch(url[,data[,config]])
并发 Concurrency
- axios.all(iterable):类似
Promise.all;接受一个数组作为参数,数组中的每个元素都是一个请求,返回一个promise对象,当数组中所有请求均已完成时,执行then方法。 - axios.spread(callback):接收一个函数作为参数,返回一个新的函数
function getUserAuth(){
return axios.get('/auth/xxxx');
}
function getUserMenu(){
return axios.get('/auth/xxxx/permissions');
}
axios.all([getUserAuth(), getUserMenu()])
.then(axios.spread(function(acc,pers){
console.log('两个请求已完成')
})
);
Requeset Config请求设置
1.url: 必填 用于请求的服务器URL
url: '/Auth/xxxxx',
2.baseURL: 非必填 如果url不是绝对地址,那么将会加在其前面 可对相对地址的axios实例设置baseUrl
baseURL: 'https://xxx.com/api/',
3.proxy:非必填 定义代理服务器的主机名、端口、auth
- auth定义HTTP应该跟proxy连接的基本认证,并且提供证书
- 将设置一个Proxy-Authorization头(header),覆盖原先自定义
proxy: {
host: '127.0.0.1',
port: 9000,
auth: {username: 'cdd', password: '123456'}
},
4.method: 非必填 发起请求时的方法 默认get
method: 'get',
**5.headers:非必填 自定义的要被发送的信息头 **
headers: {'X-Requested-with': 'XMLHttpRequest'},
6.params:请求参数,必须是一个纯对象,或者URLSearchParams对象
params: { ID: 12345 },
7.data:非必填 请求主体发送的数据对象
- 适用于发送POST、PUT或者PATCH请求的数据对象
- 当没设置transformRequest时,必须是以下类型之一: string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
- Browser only(限浏览器): FormData, File, Blob
- Node only(限Node): Stream
data: { firstName: 'fred' },
8.timeout:非必填 指定请求超时之前的毫秒数
timeout: 1000,
9.withCredentials: 非必填 设置跨跨域请求书否需要证明
withCredentials: false, //默认值
10.auth:非必填 提供凭证用于完成http的身份验证
将会在headers中设置一个Authorization授权信息。自定义Authorization授权要设置在headers中
auth: {
username: '',
password: ''
},
11.responseType:非必填 服务器返回的数据类型
// arraybuffer、blob、document、json、text、stream
responseType: 'json',
12.responseEncoding:非必填 解析相应的编码方式
注:会忽视responseType为stream或者客户端的请求。
responseEncoding: 'utf8', //默认值
13.onUploadProgress:处理上传过程的进程事件
onUploadProgress: function (progressEvent) { //本地过程事件发生时想做的事 },
14.onDownloadProgress:处理下载过程的进程事件
onDownloadProgress: function (progressEvent) { //下载过程中想做的事 },
15.maxContentLength:非必填 定义接收到的response响应数据的最大字节容量
maxContentLength: 2000,
16.adapter:适配器 允许自定义处理请求,返回一个promise和一个有效的response
adapter: function (config) {
/*...*/
},
17.httpAgent:非必填 定义在nodejs用http请求时的代理 允许配置类似keepAlive的选项
httpAgent: new http.Agent({keepAlive: true}),
18.httpsAgent:非必填 定义在nodejs用https请求时的代理 允许配置类似keepAlive的选项
httpsAgent: new https.Agent({keepAlive: true}),
19.transformRequest:非必填 允许请求的数据在发送至服务器之前进行转化
- 只适用于
PUT,POST,PATCH方法,并且必须返回一个string、ArrayBuffer或Stream象
transformRequest: [function (data, headers) {
//依自己的需求对请求数据进行处理
return data;
}],
20.transformResponse:非必填 允许对返回的数据传入then/catch之前进行处理
transformResponse: [function (data) {
//依需要对数据进行处理
return data;
}],
21.paramsSerializer:非必填 是params参数序列化器
paramsSerializer: function (params) {
return Qs.stringify(params, {arrayFormat: 'brackets'})
},
21.xsrfCookieName:非必填 设置xsrf token 值的 cookie 名称
xsrfCookieName: 'XSRF-TOKEN',//默认值
23.xsrfHeaderName:非必填 设置xsrf token 值的 http head 名称
xsrfHeaderName: 'X-XSRF-TOKEN',//默认值
24.validateStatus:非必填 设置是否解析或拒绝给定的promise
- HTTP响应状态码,若返回true,promise将被解析;若返回false,promise将被拒绝。
- 若设置为null、undefined, promise将被解析
validateStatus: function (status) {
return status >= 200 && stauts < 300;//默认
},
25.maxRedirects:非必填 在node.js中redirect的最大值 为0时没有redirect
maxRedirects: 5,//默认值
26.socketPath:非必填 数据转发
- 在node.js中使用的UNIX Socket
- socketPath和proxy二选一,若都定义,则使用socketPath
socketPath: null,//默认值
27.cancelToken:非必填 用于取消请求
cancelToken: new CancelToken(function (cancel) {})
Response Schema
- data:服务器的提供的回复(相对于请求)
data{}, - status:服务器返回的http状态码
status:200, - statusText:服务器返回的http状态信息
statusText: 'ok', - headers:服务器返回中携带的headers
headers:{}, - config:对axios进行的设置,目的是为了请求(request)
config:{} - request:获取当前相应的请求
- 是node.js中最后一次的ClientRequest的实例(在redirect中)
- 或者是在浏览器中的XMLHttpREquest实例
axios无感刷新token
在响应拦截器中拦截,判断token 返回过期后,调用刷新token接口
import axios from 'axios'
// 拦截器
axios.interceptors.response.use(
response => {
if (response.data.code === 409) {
if (!isRefreshing) {
isRefreshing = true
return refreshToken({
refreshToken: localStorage.getItem('refreshToken'),
token: getToken()
}).then(res => {
const { token } = res.data
setToken(token)
response.headers.Authorization = `${token}`
}).catch(err => {
removeToken()
router.push('/login')
return Promise.reject(err)
}).finally(() => {
isRefreshing = false
})
}
}
return response && response.data
},
(error) => {
Message.error(error.response.data.msg)
return Promise.reject(error)
}
)
Fetch
Fetch是基于promise设计的,是原生js API,没有使用XMLHttpRequest对象,返回一个promise对象
兼容性查询:caniuse.com/?search=fet…
Fetch优点
- 语法简洁,更加语义化
- 基于标准 Promise 实现,支持 async/await
- 同构方便,更加底层,提供的API丰富(request, response, body , headers)
- 脱离了XHR,是ES规范里新的实现方式
Fetch缺点
fetch只对网络请求报错,对400,500都当做成功的请求,服务器返回 400,500 错误码时并不会 reject。fetch默认不会带cookie,需要添加配置项: fetch(url,{credentials:'include'})。fetch不支持abort,不支持超时控制,使用 setTimeout 及promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了流量的浪费。fetch没有办法原生监测请求的进度,上传文件时,无法进度检测,而XHR可以
fetchAPI
- URL:请求地址
- Config:配置对象,定制发出的 HTTP 请求。
fetch(url, Config)
Requeset Config请求设置
1.mode
指定请求的模式,
cors:默认值,允许跨域请求。same-origin:只允许同源请求。no-cors:请求方法只限于 GET、POST 和 HEAD,并且只能使用有限的几个简单标头,不能添加跨域的复杂标头,相当于提交表单所能发出的请求。
2.credentials
指定是否发送 Cookie,跨域请求发送 Cookie,需设为include
same-origin:默认值,同源请求时发送 Cookie,跨域请求时不发送。include:不管同源请求,还是跨域请求,一律发送 Cookie。omit:一律不发送
3.method
HTTP 请求的方法,POST、DELETE、PUT都在这个属性设置。
4.headers
一个对象,用来定制 HTTP 请求的标头。
5.body
post请求的数据体。
- 默认方式
const response = await fetch(url, {
method: 'POST',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8",
},
body: 'foo=bar&lorem=ipsum',
});
const json = await response.json();
- json方式
const user = { name: 'John', surname: 'Smith' };
const response = await fetch('/article/fetch/post/user', {
method: 'POST',
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
body: JSON.stringify(user)
});
- 表单方式
const form = document.querySelector('form');
const response = await fetch('/users', {
method: 'POST',
body: new FormData(form)
})
- 文件上传方式
const input = document.querySelector('input[type="file"]');
const data = new FormData();
data.append('file', input.files[0]);
data.append('user', 'foo');
fetch('/avatars', {
method: 'POST',
body: data
});
- 二进制方式
let blob = await new Promise(resolve =>
canvasElem.toBlob(resolve, 'image/png')
);
let response = await fetch('/article/fetch/post/image', {
method: 'POST',
body: blob
})
6.cache
指定如何处理缓存
default:默认值,先在缓存里面寻找匹配的请求。no-store:直接请求远程服务器,并且不更新缓存。reload:直接请求远程服务器,并且更新缓存。no-cache:将服务器资源跟本地缓存进行比较,有新的版本才使用服务器资源,否则使用缓存。force-cache:缓存优先,只有不存在缓存的情况下,才请求远程服务器。only-if-cached:只检查缓存,如果缓存里面不存在,将返回504错误。
7.referrer
用于设定fetch()请求的referer标头,字符串类型,空字符串(表示部分发送referer标头。
fetch('/page', {
referrer: ''
});
8.referrerPolicy
no-referrer-when-downgrade:默认值,总是发送Referer标头,除非从 HTTPS 页面请求 HTTP 资源时不发送。no-referrer:不发送Referer标头。origin:Referer标头只包含域名,不包含完整的路径。origin-when-cross-origin:同源请求Referer标头包含完整的路径,跨域请求只包含域名。same-origin:跨域请求不发送Referer,同源请求发送。strict-origin:Referer标头只包含域名,HTTPS 页面请求 HTTP 资源时不发送Referer标头。strict-origin-when-cross-origin:同源请求时Referer标头包含完整路径,跨域请求时只包含域名,HTTPS 页面请求 HTTP 资源时不发送该标头。unsafe-url:不管什么情况,总是发送Referer标头。
9.redirect
指定 HTTP 跳转的处理方法
follow:默认值,跟随 HTTP 跳转。error:如果发生跳转,fetch()就报错。manual:不跟随 HTTP 跳转,但是response.url属性会指向新的 URL,response.redirected属性会变为true,由开发者自己决定后续如何处理跳转。
10.integrity
指定一个哈希值,用于检查 HTTP 回应传回的数据是否等于这个预先设定的哈希值。
// 检查下载文件的 SHA-256 哈希值是否相符,确保没有被篡改
fetch('http://site.com/file', {
integrity: 'sha256-abcdef'
});
11.keepalive
当页面卸载时,浏览器在后台是否保持连接,继续发送数据
window.onunload = function() {
fetch('/analytics', {
method: 'POST',
body: "statistics",
keepalive: true // 默认 false
});
};
12.signal
指定一个 AbortSignal 实例,用于取消请求
//新建实例
let controller = new AbortController();
let signal = controller.signal;
//发送请求
fetch(url, {
signal: controller.signal
});
// 监听abort
signal.addEventListener('abort',
() => console.log('abort!')
);
controller.abort(); // 取消
console.log(signal.aborted); // true
Responses属性及方法
1.ok
返回一个布尔值,表示请求是否成功
true对应 HTTP 请求的状态码 200 到 299;false对应其他的状态码。
2.status
返回一个数字,表示 HTTP 回应的状态码(例如200,表示成功请求)。
3.statusText
返回一个字符串,表示 HTTP 回应的状态信息(例如请求成功以后,服务器返回"OK")。
4.url
返回请求的 URL。如果 URL 存在跳转,该属性返回的是最终 URL。
5.type
返回请求的类型。可能的值如下:
basic:普通请求,即同源请求。cors:跨域请求。error:网络错误,主要用于 Service Worker。opaque:如果fetch()请求的type属性设为no-cors,就会返回这个值,详见请求部分。表示发出的是简单的跨域请求,类似<form>表单的那种跨域请求。
6.opaqueredirect
如果fetch()请求的redirect属性设为manual,就会返回这个值,详见请求部分。
7.body
Response 对象暴露出的底层接口,返回一个 ReadableStream 对象,供用户操作。
它可以用来分块读取内容,应用之一就是显示下载的进度。
const response = await fetch('flower.jpg');
const reader = response.body.getReader();
while(true) {
const {done, value} = await reader.read();
if (done) {
break;
}
console.log(`Received ${value.length} bytes`)
}
上面示例中,response.body.getReader()方法返回一个遍历器。这个遍历器的read()方法每次返回一个对象,表示本次读取的内容块。
这个对象的done属性是一个布尔值,用来判断有没有读完;value属性是一个 arrayBuffer 数组,表示内容块的内容,而value.length属性是当前块的大小。
8.text()
用于获取文本数据,比如 HTML 文件。
const response = await fetch('/users.html');
const body = await response.text();
document.body.innerHTML = body
9.json()
于获取服务器返回的 JSON 数据。
fetch('https://api.github.com/users/ruanyf')
.then(response => response.json())
.then(json => console.log(json))
.catch(err => console.log('Request Failed', err));
10.formData()
主要用在 Service Worker 里面,拦截用户提交的表单,修改某些数据以后,再提交给服务器。
11.blob()
用于获取二进制文件。
const response = await fetch('flower.jpg');
const myBlob = await response.blob();
const objectURL = URL.createObjectURL(myBlob);
const myImage = document.querySelector('img');
myImage.src = objectURL; // 显示在网页上
12.arrayBuffer()
用于获取流媒体文件。
// 获取音频文件`song.ogg`后在线播放
const audioCtx = new window.AudioContext();
const source = audioCtx.createBufferSource();
const response = await fetch('song.ogg');
const buffer = await response.arrayBuffer();
const decodeData = await audioCtx.decodeAudioData(buffer);
source.buffer = buffer;
source.connect(audioCtx.destination);
source.loop = true;
13.clone()
创建Response对象的副本,实现多次读取。
//由于Stream 对象只能读取一次,再次读取会报错
let text = await response.text(); // 第一次读取
let json = await response.json(); // 再次读取 报错
正确用法
const response1 = await fetch('flowers.jpg');
const response2 = response1.clone();
const myBlob1 = await response1.blob();
const myBlob2 = await response2.blob();
image1.src = URL.createObjectURL(myBlob1);
image2.src = URL.createObjectURL(myBlob2);
14.redirect()
将 Response 结果重定向到指定的 URL。该方法一般只用在 Service Worker 里面
fetch 并发请求
function handleFetchQueue(urls, max, callback) {
const urlCount = urls.length;
const requestsQueue = [];
const results = [];
let i = 0;
const handleRequest = (url) => {
const req = fetch(url).then(res => {
console.log('当前并发: '+requestsQueue);
const len = results.push(res);
if (len < urlCount && i + 1 < urlCount) {
requestsQueue.shift();
handleRequest(urls[++i])
} else if (len === urlCount) {
('function' === typeof callback) && callback(results)
}
}).catch(e => {
results.push(e)
});
if (requestsQueue.push(req) < max) {
handleRequest(urls[++i])
}
};
handleRequest(urls[i])
}
const urls = Array.from({length: 10}, (v, k) => k);
const fetch = function (idx) {
return new Promise(resolve => {
console.log(`start request ${idx}`);
const timeout = parseInt(Math.random() * 1e4);
setTimeout(() => {
console.log(`end request ${idx}`);
resolve(idx)
}, timeout)
})
};
const max = 4;
const callback = () => {
console.log('run callback');
};
handleFetchQueue(urls, max, callback);