📠 一、Ajax(XHR)
1、Ajax
Ajax:全称 Asynchronous JavaScript + XML(异步 JavaScript 和 XML)
- Ajax 出现前,任何和服务器的交互都需要刷新页面,用户体验非常差
- Ajax 出现后,网页应用能够快速地将增量更新呈现在用户界面上,不需重载(刷新)整个页面
2、XHR
浏览器的 XMLHttpRequest 是实现 Ajax 最重要的对象,由let xhr = new XMLHttpRequest();创建一 xhr 实例
方法
- open:初始化一个请求。
xhr.open(method, url, async); - send:发送 HTTP 请求。
xhr.send(param); - abort:终止一个 ajax 请求。
xhr.abort(),readyState 将被设置为 0 - setRequestHeader:设置 http 请求头。
xhr.setRequestHeader(header, value);在 open()、send()间调用 - getResponseHeader:获取 http 返回头。
let header= xhr.getResponseHeader(name);
- open:初始化一个请求。
属性
- readyState:标识当前 XMLHttpRequest 对象所处的状态
- status:表示 http 请求的状态, 初始值为 0。如果服务器没有显式地指定状态码, 那么 status 将被设置为默认值, 即 200。
- responseType:表示响应的数据类型,并允许我们手动设置,如果为空,默认为 text 类型
- response:返回响应的正文
- withCredentials:withCredentials 的属性为 true 将允许携带跨域 cookie
事件回调
- onreadystatechange:当 readyState 属性发生变化时,callback 会被触发。
- onloadstart:在 ajax 请求发送之前(
readyState==1后,readyState==2前),callback 会被触发。 onprogress:回调函数可以获取资源总大小 total,已经加载的资源大小 loaded,用这两个值可以计算加载进度。
xhr.onprogress = function(event){console.log(event.loaded / event.total);}
- onload:当一个资源及其依赖资源已完成加载时,将触发 callback,通常我们会在 onload 事件中处理返回值
异常处理
- onerror:当 ajax 资源加载失败时会触发 callback。
- ontimeout:当进度由于预定时间到期而终止时,会触发 callback,超时时间可使用 timeout 属性进行设置。
let xhr = new XMLHttpRequest();xhr.open("GET", "/my/url");xhr.withCredentials = true;xhr.setRequestHeader("Content-Type", "application/json");xhr.responseType = "json";xhr.send();xhr.onload = function () {if (xhr.status != 200) {// HTTP 出错?// 处理错误alert("Error: " + xhr.status);return;}// 从 xhr.response 中获取响应};xhr.onerror = function () {console.log("Network request failed");};
🏄二、Fetch
Fetch API 是一个用于访问和操纵 HTTP 管道的强大的原生 API
1、请求
浏览器立即发送请求,并返回一个 promise
const options = {method: "POST",mode: "cors" // 跨域headers: {"Content-Type": "application/json"}, // 设置请求头body: JSON.stringify({ name: "123" }), // 请求参数credentials: "include", // 需发送凭据};let promise = fetch(url, options);
2、获取响应状态并解析响应体
属性
- response.ok —— 布尔值,若 HTTP 状态码在 200-299 之间,返回 true
- response.status —— HTTP 状态码
- response.headers —— 类似于 Map 的 headers 对象,可获取单个或迭代它们
response.body —— ReadableStream 对象,允许逐块读取正文,追踪 download 过程
启动 fetch 并赋值给 reader(流读取器):
const reader = response.body.getReader();
从 Content-Length 头中找出完整响应长度,获得总长度(总块数)
const contentLength = +response.headers.get('Content-Length');
- 读取数据,调用
await reader.read()直到它已经完成 - 将块合并成单个
Uint8Array字节块 - 解码成字符串
方法:Response 提供了多种基于 promise 方法来获取不同格式的响应正文
- response.json() —— 将 response 解析为 JSON 对象
- response.text() —— 以文本形式返回 response
- response.formData() —— 以 FormData 对象(form/multipart 编码)的形式返回 response
- response.blob() —— 以 Blob(具有类型的二进制数据)形式返回 response
- response.arrayBuffer() —— 以 ArrayBuffer(纯二进制数据)形式返回 response
//await方法let response = await fetch(url, options); //解析 response headersif (response.ok) {// 如果 HTTP 状态码在 200-299 之间,获取响应体(如下所示)let result = await response.json(); // 以 JSON 形式读取数据console.log(result);} else {alert("HTTP-Error: " + response.status);}//纯 promise 方法fetch(url, options).then((response) => response.json()).then((result) => {console.log(result);}) // 响应数据.catch((err) => {console.log(err);}); // 异常处理
3、中止(abort)
一个特殊的内置对象:AbortController。可扩展的,它允许同时取消多个 fetch
// 1 秒后中止let controller = new AbortController();setTimeout(() => controller.abort(), 1000);try {let response = await fetch(url, {signal: controller.signal,});} catch (err) {if (err.name == "AbortError") {// handle abort()alert("Aborted!");} else {throw err;}}
🎷三、Axios
axios 功能:从浏览器中创建 XMLHttpRequests、从 node.js 创建 http 请求、支持 Promise API、拦截请求和响应、转换请求数据和响应数据、取消请求、自动转换 JSON 数据、客户端支持防御 XSRF
1、axios API
- axios(config)
// GET request for remote imageaxios({method: "get",url: "http://bit.ly/2mTM3nY",responseType: "stream",}).then(function (response) {response.data.pipe(fs.createWriteStream("ada_lovelace.jpg"));});
- axios(url[,config]):
axios('/user/12345');// Send a GET request (default)
2、别名请求方法
- 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]])
3、请求配置选项
{url: '/user',method: 'get', // defaultbaseURL: 'https://some-domain.com/api/',transformRequest: [function (data, headers) {// transformRequest方法允许在请求发送到服务器之前修改该请求// 只适用于PUT、POST、PATCH方法中// 最后必须返回一个string、ArrayBuffer或者Stream。return data;}],transformResponse: [function (data) {// transformResponse方法允许在数据传递到then/catch之前修改response数据// 此方法最后也要返回数据return data;}],headers: {'X-Requested-With': 'XMLHttpRequest'},// 发送自定义Headers头文件params: {ID: 12345},// 发送请求的查询参数对象,拼接成 url?param1=value1¶m2=value2data: {firstName: 'Fred'},// data是在发送POST、PUT或者PATCH请求的数据对象timeout: 1000, // default is `0` (no timeout)withCredentials: false, // defaultadapter: function (config) {/* adapter允许用户处理更易于测试的请求。返回Promise和一个有效的response */},auth: {// auth表明提供凭证用于完成http的身份验证。//这将会在headers中设置一个Authorization授权信息。//自定义Authorization授权要设置在headers中username: 'janedoe',password: 's00pers3cret'},responseType: 'json', // defaultresponseEncoding: 'utf8', // defaultxsrfCookieName: 'XSRF-TOKEN', // defaultxsrfHeaderName: 'X-XSRF-TOKEN', // defaultonUploadProgress: function (progressEvent) {// Do whatever you want with the native progress event},onDownloadProgress: function (progressEvent) {// Do whatever you want with the native progress event},maxContentLength: 2000,validateStatus: function (status) {return status >= 200 && status < 300; // default},maxRedirects: 5, // defaultsocketPath: null, // defaulthttpAgent: new http.Agent({ keepAlive: true }),httpsAgent: new https.Agent({ keepAlive: true }),proxy: {host: '127.0.0.1',port: 9000,auth: {username: 'mikeymike',password: 'rapunz3l'}},cancelToken: new CancelToken(function (cancel) {})}
4、响应信息
{// `data` is the response that was provided by the serverdata: {},status: 200,statusText: 'OK',headers: {},config: {},request: {}}
5、拦截器
// Add a request interceptoraxios.interceptors.request.use(function (config) {// Do something before request is sentreturn config;},function (error) {// Do something with request errorreturn Promise.reject(error);});// Add a response interceptoraxios.interceptors.response.use(function (response) {// Any status code that lie within the range of 2xx cause this function to trigger// Do something with response datareturn response;},function (error) {// Any status codes that falls outside the range of 2xx cause this function to trigger// Do something with response errorreturn Promise.reject(error);});//delete interceptorconst myInterceptor = axios.interceptors.request.use(function () {/*...*/});axios.interceptors.request.eject(myInterceptor);//add interceptors to a custom instance of axios.const instance = axios.create();instance.interceptors.request.use(function () {/*...*/});
👿四、Fetch、Axios 区别实例
post 请求
- Fetch 实现:
url作为第一参数;配置项body属性提供需传输的数据,且需JSON.stringify手动序列化;获取响应数据使用response.json()
let url = "https://someurl.com";let options = {method: "POST",mode: "cors",headers: {Accept: "application/json","Content-Type": "application/json;charset=UTF-8",},body: JSON.stringify({property_one: value_one,property_two: value_two,}),};//await方法let response = await fetch(url, options);if (response.ok) {let data = await response.json();// do something with data} else {alert("HTTP-Error: " + response.status);}//promise方法fetch(url, options).then((response) => response.json()).then((data) => {console.log(data);}).catch((err) => {console.log(err);});
- Axios 实现:配置项作为唯一对象参数,包含
url;data属性提供需传输的数据,不需手动序列化;获取响应数据使用response.data
let url = "https://someurl.com";let options = {method: "POST",url: url,headers: {Accept: "application/json","Content-Type": "application/json;charset=UTF-8",},data: {property_one: value_one,property_two: value_two,},};//await方法let response = await axios(options);if (response.status === 200 && response.statusText === "OK") {let data = await response.data;// do something with data}//promise方法axios(options).then((response) => response.data).then((data) => {console.log(data);}).catch((err) => {console.log(err);});
