三者简介与各自的优劣
Ajax
Ajax(Asynchronous JavaScript And XML): 本身并不是一种技术,核心是使用 XMLHttpRequest
对象完成异步请求,可以在不重新刷新页面的情况下与服务器通信,交换数据,或更新页面。
优势(虽说技术老旧,但是大部分优势均是 XHR-level2 升级后的,仅支持 IE10+):
- 可发送跨域请求(服务端允许的情况下);
- 支持二进制数据;
- 支持 formData 对象,发送表单数据;
- 可获取进度信息;
- 可设置请求超时时间;
劣势:
- 不符合关注分离,将输入、输出和用事件来跟踪的状态混杂在一个对象里;
- 不支持现代 Promise,async/await;
- 数据类型处理、错误处理等都不易操作;(上述缺点都需要封装才能在真实环境中使用)
Fetch
Fetch: Fetch API 是 JS 提供了一个获取资源的接口(底层接口,等同于 XMLHttpRequest
),被设计成更具可扩展性和高效性,Fetch 的核心在于对 HTTP 接口的抽象,包括 Request
,Response
,Headers
,Body
等。
优势:
- 语法简洁,更加语义化
- 基于 Promise 实现,支持 async/await
- 脱离了 XHR,提供更多 API(request,response 等)
劣势:
- 只对网络请求报错,对 404/500 等都是成功请求,并不会 reject,只有网络请求出错才会 reject;
- 默认不携带 cookie,需添加配置项
fetch(url, {credentials: 'include'})
- 不支持 abort 终止请求、超时控制,使用
setTimeout
及Promise.reject
实现的超时控制并不能阻止请求过程,造成流量的浪费; - 无法原生检测请求进度,而 XHR 可以;
- 浏览器兼容问题,且目前很多特性仍为实验性;
Axios
Axios: 是一个基于 promise 的第三方 HTTP 库,可以用在浏览器和 node.js 中。浏览器中就是基于 XMLHttpRequest
封装的 http 库;
优势:
- 支持 Promise
- 客户端支持防止 CSRF,防御 XSRF
- 丰富的接口 API(并发请求等)
- 请求/响应拦截器
- 转换请求和响应数据(自动转换 JSON 数据等)
- 取消阻止请求
劣势:
- 非原生,第三方
综上所述,个人认为在 Fetch 完善且大部分支持前, Axios 仍是目前最好的异步请求方案。
使用
Ajax
简例:
1 | let xhr = new XMLHttpRequest(); |
如上例所示,XHR 的劣势之一:不符合关注分离,将输入、输出和用事件来跟踪的状态混杂在一个对象里。
XMLHttpRequest
实例属性与方法:
onreadystatechange
: 监听请求状态(readyState)改变方法setRequestHeader(key, value)
: 设置请求头open(method, url, isAsync)
: 设置请求send(data)
: 发送请求onload
: 请求完成回调onerror
: 请求失败回调readyState
: 请求状态0
: 请求还未初始化1
: 已建立服务器链接2
: 请求已接受3
: 正在处理请求4
: 请求已完成并且响应已准备好
status
: 响应代码200
、304
、400
等
封装
使用 promise,数据处理,设置请求头。
1 | // 封装 |
Fetch
简例:上传 JSON 数据(加*为属性默认值)
1 | // 上传 JSON 数据 |
请求参数
fetch(url, options)
第二参数为请求参数,可选配置:
method
: 请求使用的方法;headers
: 请求头信息;body
: 请求的 body 信息:可能是一个 Blob、BufferSource、FormData、URLSearchParams 或者 USVString 对象。注意 GET 或 HEAD 方法的请求不能包含 body 信息;mode
: 请求的模式,(cors、 no-cors、same-origin);credentials
: 请求发送凭证 cookie 模式。omit
: 默认,不发送;same-origin
: 同源发送;include
: 发送,即使跨域;
cache
: 请求的缓存模式,有如下几种值:default
: 根据浏览器 HTTP 缓存匹配,强缓存协商缓存等直接走缓存;no-store
: 直接从服务器获取资源,不查看缓存也不会更新缓存;reload
: 直接从服务器获取资源,不查看缓存但更新缓存;no-cache
: 命中强缓存仍发送请求,资源没更新,则取缓存资源(即协商缓存),无缓存则发送正常请求;force-cache
: 有缓存时强制使用缓存,无缓存时正常发送请求;only-if-cached
: 有缓存都使用缓存,无缓存报错;
redirect
: 重定向模式: follow (自动重定向), error (如果产生重定向将自动终止并且抛出一个错误), 或者 manual (手动处理重定向). 在 Chrome 中,Chrome 47 之前的默认值是 follow,从 Chrome 47 开始是 manual。referrer
: 请求来源,可以是 no-referrer、client 或一个同源 URL。默认是 client。referrerPolicy
: 指定了 HTTP 头部 referer 字段的值。可能为以下值之一: no-referrer、 no-referrer-when-downgrade、 origin、 origin-when-cross-origin、 unsafe-url 。integrity
: 包括请求的 subresource integrity 值 ( 例如: sha256-BpfBw7ivV8q2jLiT13fxDYAe2tJllusRSZ273h2nFSE=)。
自定义请求对象
除了直接 fetch()
传入 url 和配置外,还可直接接收 Request() 构造函数来创建的请求对象,且 Headers() 构造函数可以创建 headers 对象,但两者均还是实验中功能,仅新浏览器支持。
1 | var myHeaders = new Headers() |
Headers()
创建 headers 对象的其它方法;
1 | // append() 方法添加 |
可设置的 header:
- Accept-Charset, Accept-Encoding
- Access-Control-Request-Headers
- Access-Control-Request-Method
- Connection
- Content-Length
- Cookie, Cookie2
- Date
- DNT
- Expect
- Host
- Keep-Alive
- Origin
- Referer
- TE
- Trailer
- Transfer-Encoding
- Upgrade
- Via
- Proxy-*
- Sec-*
当然,浏览器为了安全等原因,还有一些无法设置的 header(详见:whatwg - forbidden header name,whatwg 是一个由各浏览器大佬发起的组织,且一度和 w3c 组织吵架)
Response 对象
常见响应对象属性和方法有:
response.status
: Number,响应状态码;response.statusText
: String,响应状态消息;response.ok
: Boolean,状态码在 200-299 内为true
;response.headers
: Object,响应头 headers 对象;response.text()
: 读取 response,并以文本形式返回 response;response.json()
: 将 response 解析为 JSON 对象形式;response.formData()
: 以 FormData 对象的形式返回;response.blob()
: 以 Blob(具有类型的二进制数据)形式返回;response.arrayBuffer()
: 以 ArrayBuffer(低级别的二进制数据)形式返回;
检测请求是否成功
上述 Fetch 缺点中也提到了,Fetch只对网络请求报错,对 404/500 等都是成功请求,只有网络请求出错才会 reject;检测是否非网络故障报错需要对响应做判断,简单实现如下:
1 | fetch('flowers.jpg') |
上传多个文件例子
HTML <input id="files" type="file" multiple>
结合 FormData()
;
1 | var formData = new FormData() |
Axios
关于 Axios 的使用,可参考我的另一篇博客文章,详细介绍了 Axios API、请求参数、响应对象、实例使用、拦截器、封装 等,详见:Axios HTTP 库的使用 - 前端随笔
参考资料:
- MDN - Ajax
- MDN - Using Fetch
- MDN - WindowOrWorkerGlobalScope.fetch()