1.axios
1.1 What is axios?
- The most popular ajax request library on the front end
- react/vue officially recommends using axios to send ajax requests
- Documentation:
https://github.com/axios/axiosopen
1.2 Features of axios
- Asynchronous ajax request library based on xhr + promise
- Both browser and node can be used
- Support for request/response interceptors
- Support Request Cancellation
- Request/Response Data Conversion
- Batch multiple requests
1.3 Axios common syntax
axios(config): the general/most essential way to send any type of request
axios(url[, config]): You can only specify the url to send a get request
axios.request(config): equivalent to axios(config)
axios.get(url[, config]): send a get request
axios.delete(url[, config]): send delete request
axios.post(url[, data, config]): send a post request
axios.put(url[, data, config]): send put request
axios.defaults.xxx: The default global configuration of the request (method\baseURL\params\timeout…)
axios.interceptors.request.use(): add request interceptor
axios.interceptors.response.use(): add response interceptor
axios.create([config]): Create a new axios (it does not have the following functions)
axios.Cancel(): Error object used to create a cancellation request
axios.CancelToken(): A token object used to create a cancellation request
axios.isCancel(): Is it an error to cancel the request
axios.all(promises): used to execute multiple asynchronous requests in batches
axios.spread(): A method used to specify a callback function that receives all successful data
1.4 use
Commonly used configuration items for configuration objects
{
// 路径url
url: '/user',
// 请求方法,默认get
method: 'get',
//基础url,最终请求的url是 baseURL+url拼接,所以再全局设置默认,可以使得发送请求时的url变得简洁
baseURL: 'https://some-domain.com/api/',
//设置请求头
headers: {
'X-Requested-With': 'XMLHttpRequest'},
//设置请求url的query参数,可以使得url简洁。
//比如url是https://some-domain.com/api/user 然后params如下设置,那么最终的url是:
//https://some-domain.com/api/user?ID=12345&name=Jack
params: {
ID: 12345,
name:"Jack"
},
//设置请求体
data: {
firstName: 'Fred'
},
//设置请求的另外一种格式,不过这个是直接设置字符串的
data: 'Country=Brasil&City=Belo Horizonte',
//请求超时,单位毫秒,默认0,不超时。
timeout: 1000,
//响应数据类型,默认json
responseType: 'json',
//响应数据的编码规则,默认utf-8
responseEncoding: 'utf8',
//响应体的最大长度
maxContentLength: 2000,
// 请求体的最大长度
maxBodyLength: 2000,
//设置响应状态码为多少时是成功,调用resolve,否则调用reject失败
//默认是大于等于200,小于300
validateStatus: function (status) {
return status >= 200 && status < 300;
}
the code
<button id="btn1">发送get请求</button> <br><br>
<button id="btn2">发送post请求</button><br><br>
<button id="btn3">发送put请求</button><br><br>
<button id="btn4">发送delete请求</button>
<hr>
<div>其他发送请求的api:</div><br><br>
<button id="btn5">发送get请求1</button> <br><br>
<button id="btn6">发送post请求1</button><br><br>
<button id="btn7">发送put请求1</button><br><br>
<button id="btn8">发送delete请求1</button>
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
//发送get
document.getElementById("btn1").onclick = function(){
axios({
method:"GET",
url:"http://localhost:3000/posts/1"
}).then(response=>{
console.log(response);
})
};
//发送post
document.getElementById("btn2").onclick = function(){
axios({
method:"POST",
url:"http://localhost:3000/posts",
data:{
title:"axios学习",
author:"Yehaocong"
}
}).then(response=>{
console.log(response);
})
};
//发送put
document.getElementById("btn3").onclick = function(){
axios({
method:"PUT",
url:"http://localhost:3000/posts/2",
data:{
title:"axios学习",
author:"Liaoxiaoyan"
}
}).then(response=>{
console.log(response);
})
};
document.getElementById("btn4").onclick = function(){
axios({
method:"DELETE",
url:"http://localhost:3000/posts/2",
}).then(response=>{
console.log(response);
})
};
//其他发送请求的api
document.getElementById("btn5").onclick = function(){
//发送get,使用get,第一个参数时url,第二个参数时config配置对象
axios.get("http://localhost:3000/posts/1")
.then(response=>{
console.log(response);
})
};
//发送post
document.getElementById("btn6").onclick = function(){
//发送post请求,第一个参数时url,第二个参数时请求体,第三个参数时config配置对象
axios.post("http://localhost:3000/posts",
{
title:"axios学习2",
author:"Yehaocong2"})
.then(response=>{
console.log(response);
})
};
//发送put,
document.getElementById("btn7").onclick = function(){
//发送put,接收三个参数,url 请求体 、 config配置对象
axios.put("http://localhost:3000/posts/2",{
title:"axios学习",
author:"Liaoxiaoyan"})
.then(response=>{
console.log(response);
})
};
document.getElementById("btn8").onclick = function(){
//发送delete请求,接收2个参数, url config配置对象
axios.delete("http://localhost:3000/posts/3")
.then(response=>{
console.log(response);
})
};
default allocation
The global default configuration can be set to avoid multiple repeated configurations repeated in different requests, such as baseURL, timeout, etc., set baseURL here.
axios.defaults.baseURL="http://localhost:3000";
//因为上面配置了baseURL,所以我们之后的请求只需要配置url不用像之前那样的全路径
axios.get("/posts/1")
.then(response=>{
console.log(response);
})
1.5 Create a new axios object
Create a new axios according to the specified configuration, that is, each new axios has its own configuration new axios, but there is no method to cancel the request and send the request in batches. All other syntaxes are consistent. Why design this syntax?
Requirements: The configuration required by some interfaces in the project is different from that required by other interfaces, how to deal with it (for example, there are multiple baseURLs that need to be specified)
Solution: Create 2 new axios, each with its own unique configuration, which are applied to interface requests with different requirements
const instance = axios.create({
// instance是函数类型
baseURL: 'http://localhost:3000'
})
// 使用instance发Ajax请求
instance({
url: '/posts'
})
instance.get('/posts')
1.6 Interceptors
Request interceptor (before sending the request, use the function to process and detect the parameters and content of the request, if there is a problem with the request, you can directly intercept -> cancel, last-in-first-execute = the subsequent request interceptor will be executed first)
Response interceptor (preprocess the result of the response, execute first = the previous response interceptor executes first)
1) Request interceptor:
- Callback function executed before actually sending the request
- Requests can be inspected or configured for specific handling
- Failed callback function, the default passed is error
- Successful callback function, the default passed is config (must also be)
2) Response Interceptor
- Callback function to be executed after the request gets a response
- Specific processing can be done on the response data
- Successful callback function, the default passed is response
- Failed callback function, the default passed is error
3) Request converter: a function for specific processing of request header and request body data
Response converter: a function that parses the response body json string into a js object or array
- Explanation: Calling axios() does not send an ajax request immediately, but needs to go through a longer process
- Process: request interceptor 2 => request interceptor 1 => send ajax request => response interceptor 1 => response interceptor 2 => request callback
- Note: This process is chained through promises, the request interceptor passes config, and the response interceptor passes response
the code
script>
//设置一个请求拦截器,在请求拦截器中可以对请求参数进行修改
//config:配置对象
axios.interceptors.request.use(
function (config) {
console.log("请求拦截器 成功 1号");
// config.headers.test = "I am only a header!";
//修改 config 中的参数
config.params = {
a: 100 };
return config;
},
error => {
console.log("请求拦截器 失败 1号");
return Promise.reject(error);
}
);
axios.interceptors.request.use(
function (config) {
config.timeout = 5000;
console.log("请求拦截器 成功 2号");
// config.headers.test = "I am only a header!";
//修改 config 中的参数
config.timeout = 2000;
return config;
},
error => {
console.log("请求拦截器 失败 2号");
return Promise.reject(error);
}
);
//设置一个响应拦截器,可以对响应结果做一些处理
axios.interceptors.response.use(
function (response) {
console.log("响应拦截器 成功 1号");
//返回到请求回调时,只要data数据
return response.data;
},
function (error) {
console.log("响应拦截器 失败 1号");
return Promise.reject(error);
}
);
//设置一个响应拦截器
axios.interceptors.response.use(
function (response) {
console.log("响应拦截器 成功 2号");
return response;
},
function (error) {
console.log("响应拦截器 失败 2号");
return Promise.reject(error);
}
);
//发送请求
axios({
method: "GET",
url: "http://localhost:3000/posts",
})
.then((response) => {
console.log("自定义回调处理成功的结果");
//console.log(response);
})
.catch((reason) => {
console.log(reason);
});
</script>
1.7 Cancellation Request
It can be used before version 0.22, and it has been deprecated since 0.22
<body>
<div class="container">
<h1 class="page-header">axios取消请求</h1>
<button class="btn btn-primary">发送请求</button>
<button class="btn btn-warning">取消请求</button>
</div>
</body>
<script>
//获取按钮
const btns = document.querySelectorAll("button");
//2.声明一个全局变量
let cancel = null;
//发送请求
btns[0].onclick = () => {
//检测上一次请求是否已经完成
if (cancel !== null) {
//则代表上一次请求还未取消,故直接取消上一次请求
cancel();
}
axios({
method: "GET",
url: "http://localhost:3000/posts",
//1.添加配置对象的属性
cancelToken: new axios.CancelToken((c) => {
//3.将c的值赋值给cancel
cancel = c;
}),
}).then((response) => {
console.log(response);
//当请求执行完后 将cancel进行初始化设置
cancel = null;
});
};
//取消请求
btns[1].onclick = () => {
cancel();
};
</script>
0.22 new method
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.27.2/axios.min.js"></script>
let btn = document.querySelectorAll('button');
const controller = new AbortController();
btn[0].onclick = function () {
axios( {
url:'https://api.uomg.com/api/get.kg?songurl=https://node.kg.qq.com/play?s=YaCv8EYfJunVWYcH',
signal: controller.signal
}).then(function(response) {
console.log(response);
});
}
btn[1].onclick = function () {
controller.abort()
}
1.8 Encapsulating axios in vue
requests.js
//对于axios进行二次封装
import axios from 'axios';
//获取仓库:存储数据
import store from '@/store';
//axios.create方法执行,其实返回一个axios和request一样的
let requests = axios.create({
//基础路径,发请求URL携带api【发现:真实服务器接口都携带/api】
baseURL: '/api',
//超时的设置
timeout: 5000,
});
//请求拦截器:将来项目中【N个请求】,只要发请求,会触发请求拦截器!!!
requests.interceptors.request.use(config => {
//请求拦截器:请求头【header】,请求头能否给服务器携带参数
//请求拦截器:其实项目中还有一个重要的作用,给服务器携带请求们的公共的参数
if (store.state.detail.nanoid_token) config.headers.userTempId = store.state.detail.nanoid_token;
if (store.state.user.token) config.headers.token = store.state.user.token;
return config;
});
//响应拦截器:请求数据返回会执行
requests.interceptors.response.use(
res => {
//res:实质就是项目中发请求、服务器返回的数据
return res.data;
},
err => {
//温馨提示:某一天发请求,请求失败,请求失败的信息打印出来
alert(err.message);
//终止Promise链
return new Promise();
}
);
//最后需要暴露:暴露的是添加新的功能的axios,即为requests
export default requests;
use
import requests from '@/api/requests';
//注册的接口
export const reqRegister = data =>
requests({
url: `/user/passport/register`, method: 'post', data });
2.fetch
2.1 Disadvantages of XMLHttpRequest
The browser provides a native AJAX implementation class XMLHttpRequest. Based on this class instance, we can send AJAX requests to the server on the web page.
But the design of XMLHttpRequest is not perfect, mainly in the following aspects:
- HTTP requests and responses are coupled to the XMLHttpRequest instance, the structure is not simple enough
- Using event callbacks to get HTTP responses may lead to callback hell
- If the HTTP response data is too large, it will take up a lot of memory
- The last point is that the steps of XMLHttpRequest to implement AJAX are too fragmented
2.2 Advantages of fetch
Fetch, like XMLHttpRequest, is also native to the browser and is used to send AJAX requests.
It was born after XMLHttpRequest, which aims to solve the shortcomings of XMLHttpRequest, so the disadvantages of XMLHttpRequest are its advantages. The specific advantages are as follows
- Simple syntax and clear structure
- Support Promise to get asynchronous HTTP response
- HTTP response supports streaming, memory-friendly
Fetch is designed as a function, and AJAX can be initiated by calling the fetch function, without creating an instance like XMLHttpRequest, and then initiating AJAX based on the xhr instance.
fetch('http://localhost:3000/test') // fetch函数调用即发起AJAX
The fetch function returns a Promise object, and the result value of the Promise object is the HTTP response
fetch('http://localhost:3000/test').then(response => {
// fetch函数返回值是一个Promise类型对象
console.log(response) // 该Promise对象的结果值response就是HTTP响应
The HTTP response of the result value of the Promise object returned by the fetch function is obtained in a streaming manner. Even if the HTTP response data is large, it will not occupy too much memory.
2.3 fetch request and response
2.3.1 Request
fetch(url,options).then((response)=>{
//处理http响应
},(error)=>{
//处理错误
})
url: is the address to send network requests.
options: send request parameters,
-
body - http request parameters
-
mode - the requested mode
cors
: The default value, allowing cross-origin requests.same-origin
: Only same-origin requests are allowed.no-cors
: The request method is limited to GET, POST and HEAD, and only a few simple headers can be used, and cross-domain complex headers cannot be added, which is equivalent to the request that can be sent by submitting a form.
-
cache - user specified cache.
-
method - request method, default GET
-
signal - used to cancel the fetch
-
headers - HTTP request header settings
-
keepalive - When the page is unloaded, it tells the browser to keep the connection in the background and continue to send data.
-
credentials - whether to send cookies
same-origin
: The default value, cookies are sent for same-origin requests, and not sent for cross-origin requests.include
: Cookies are always sent regardless of same-origin requests or cross-domain requests.omit
: Never send.
-
referrer - the header used to set
fetch()
the requestreferer
-
referrerPolicy - used to set
Referer
header rules
- no-referrer-when-downgrade: The default value, always send the Referer header, except when requesting HTTP resources from HTTPS pages.
- no-referrer: Do not send the Referer header.
- origin: The Referer header only contains the domain name, not the full path.
- origin-when-cross-origin: Same-origin request Referer header contains the full path, cross-origin request only contains the domain name.
- same-origin: Referer is not sent for cross-origin requests, and same-origin requests are sent.
- strict-origin: The Referer header only contains the domain name, and the Referer header is not sent when an HTTPS page requests an HTTP resource.
- strict-origin-when-cross-origin: The Referer header contains the full path for same-origin requests, and only domain names for cross-origin requests.
- This header is not sent when an HTTPS page requests an HTTP resource.
- unsafe-url: Always send the Referer header no matter what.
fetch('http://localhost:3000/test',{
method: 'post',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'qfc',
age: 18
})
}).then(res => {
console.log(res)
})
What needs to be noted is the body property of the Request object, which supports
- Query parameter string, such as 'name=qfc&age=18'
- A text string such as '{"name":"qfc", "age": 18}'
- FormData object
- Blob object
- ReadableStream object
- BufferSource object
2.3.2 Response
After the fetch request is successful, the response object is as shown in the figure:
- status - http status code, ranging from 100-599
- statusText - the text description of the status returned by the server
- ok - returns a boolean value, true if the status code starts with 2, otherwise false
- headers - the response headers
- body - the response body. The data in the response body is processed according to the type.
- type - Returns the request type.
- basic: Standard value, same-origin response, with all headers except "Set-Cookie" and "Set-Cookie2".
- cors: Response A valid cross-origin request was received.
- error: Network error. No useful information describing the error. The response has status 0, headers are empty and immutable. The type of response obtained from Response.error().
- opaque: Respond to "no-cors" cross-origin requests.
- redirected - Returns a boolean indicating whether the Response came from a redirect, if so, its URL list will have multiple entries.
- url: HTTP request URL
Among them, we need to pay attention to the fact that the body attribute value is a readable stream, so we cannot directly obtain the content of the body, we need to read the content from the readable stream, and reading the content in the readable stream is also an asynchronous operation, Response considerate Provides us with the following instance methods to asynchronously obtain the content in the body readable stream
- json() reads the body content as a JSON object
- text() reads the body content as a normal text string
- formData() reads the body content as a FormData object
- blob() reads the body content as a Blob object
- arrayBuffer() reads the body content as an ArrayBuffer object
The above methods all return a Promise object, and the result value of the Promise object is the data they read and converted into the corresponding format.
fetch('http://127.0.0.1:8000/fetch-server?vip=10', {
//请求方法
method: 'POST',
//请求头
headers: {
name:'atguigu'
},
//请求体
body: 'username=admin&password=admin'
}).then(response => {
// return response.text();
return response.json();
}).then(response=>{
console.log(response);
});
Through the above code test, it is found that the result value of the Promise returned by response.json() is indeed the actual content of the body, and it is automatically converted into a JSON object.
2.4 GET and POST
2.1.1 GET
fetch(`http://localhost:80/fetch.html?user=${user.value}&pas=${pas.value}`,{
method:'GET'
}).then(response=>{
console.log('响应',response)
})
2.1.2 POST
fetch(`http://localhost:80/fetch`,{
method:'POST',
headers:{
'Content-Type':'application/x-www-form-urlencoded;charset=UTF-8'
},
body:`user=${
user.value}&pas=${
pas.value}`
}).then(response=>{
console.log('响应',response)
})
If you are submitting json data, you need to convert json into a string. like
fetch(`http://localhost:80/fetch`,{
method:'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
name: 'qfc',
age: 18
}).then(response=>{
console.log('响应',response)
})
If form data is submitted, use formData to convert it, such as:
body:new FormData(form)
Upload files can be included in the entire form and submitted together, such as:
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
});
2.5 fetch does not carry cookies by default
When passing a cookie, it must be added in the parameter credentials:'include'
, so that the current cookie will be included in the request like xhr.
2.6 Exception handling
fetch is different from xhr, xhr has its own methods such as cancel and error, so when the server returns 4xx or 5xx, no error will be thrown, and it needs to be processed manually, which can be judged by the status field in the response.
3. Cross domain
3.1 Same Origin Policy
- The Same-Origin Policy (Same-Origin Policy) was first proposed by Netscape and is a security policy for browsers.
- Same origin: protocol, domain name, port number must be exactly the same
- Cross-domain: Violation of the same-origin policy is cross-domain
3.2 How to solve cross domain
3.2.1 JSONP
jsonp only supports get requests but not post requests
1) What is JSONP
JSONP (JSON with Padding), is an unofficial cross-domain solution, developed purely with the ingenuity of programmers, and only supports get requests.
2) How does JSONP work?
Some tags on web pages are inherently capable of cross-domain, such as: img link iframe script. JSONP uses the cross-domain capabilities of script tags to send requests.
3) Use of JSONP
html code
//1. 创建 script 标签
const script = document.createElement('script');
//2. 设置标签的 src 属性
script.src = 'http://127.0.0.1:8000/check-username?callback=abc';
//3. 将script 添加到body 中
document.body.appendChild(script);
function abc(data) {
alert(data.name);
};
backend code
app.get("/check-username" , function (req , res) {
var callback = req.query.callback;
const data = {
name: '孙悟空'
};
//将数据转化为字符串
let str = JSON.stringify(data);
//返回结果(一段可执行的JavaScript代码)
response.end(`handle(${
str})`);
});
3.2.2 CORS
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
- What is CORS? CORS (Cross-Origin Resource Sharing), cross-domain resource sharing. CORS is an official cross-domain solution. Its feature is that it does not require any special operations on the client side, and it is completely processed in the server, and it supports get and post requests. A new set of HTTP header fields has been added to the cross-origin resource sharing standard, allowing the server to declare which origin sites have permission to access which resources through the browser
- How does CORS work? CORS tells the browser by setting a response header that the request allows cross-domain, and the browser will release the response after receiving the response.
- The use of CORS is mainly server-side settings:
router.get("/testAJAX" , function (req , res) {
//通过res 来设置响应头,来允许跨域请求
//res.set("Access-Control-Allow-Origin","http://127.0.0.1:3000");
res.set("Access-Control-Allow-Origin","*");//允许所有来源访问
res.send("testAJAX 返回的响应");
});