📠 一、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 headers
if (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 image
axios({
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', // default
baseURL: '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=value2
data: {
firstName: 'Fred'
},// data是在发送POST、PUT或者PATCH请求的数据对象
timeout: 1000, // default is `0` (no timeout)
withCredentials: false, // default
adapter: function (config) {
/* adapter允许用户处理更易于测试的请求。返回Promise和一个有效的response */
},
auth: {
// auth表明提供凭证用于完成http的身份验证。
//这将会在headers中设置一个Authorization授权信息。
//自定义Authorization授权要设置在headers中
username: 'janedoe',
password: 's00pers3cret'
},
responseType: 'json', // default
responseEncoding: 'utf8', // default
xsrfCookieName: 'XSRF-TOKEN', // default
xsrfHeaderName: 'X-XSRF-TOKEN', // default
onUploadProgress: 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, // default
socketPath: null, // default
httpAgent: 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 server
data: {},
status: 200,
statusText: 'OK',
headers: {},
config: {},
request: {}
}
5、拦截器
// Add a request interceptor
axios.interceptors.request.use(
function (config) {
// Do something before request is sent
return config;
},
function (error) {
// Do something with request error
return Promise.reject(error);
}
);
// Add a response interceptor
axios.interceptors.response.use(
function (response) {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
return response;
},
function (error) {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
return Promise.reject(error);
}
);
//delete interceptor
const 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);
});