目录
json-server介绍与服务搭建
1.json-server可以帮助我们快速搭建一个HTTP服务
2.在线文档: https://github.com/typicode/json-server
3.使用:
(1)在终端下载: npm install -g json-server
(2)创建数据库 json 文件: db.json
(3)在db.json中输入以下代码:
{
"posts": [
{ "id": 1, "title": "json-server", "author": "typicode" },
{ "id": 2, "title": "json-server2", "author": "typicode" }
],
"comments": [
{ "id": 1, "body": "some comment", "postId": 1 }
],
"profile": { "name": "typicode" }
}
(4)启动服务器执行命令: json-server --watch db.json
上面那行代码的意思是:启动 json-server 数据去db.json中找
(5)测试
访问所有文档:http://localhost:3000/posts
加上id就是访问指定文档:http://localhost:3000/posts/1
Axios的介绍与页面配置
1.axios:基于promise的http客户端 可以在浏览器和node.js中运行
2.特点:
(1)在浏览器中借助axio可以向服务器发送Ajax请求 在nodejs中可以使用axios向远端发送HTTP请求
(2)支持请求/响应拦截器:可以在发送请求前做一些准备工作 在请求响应回来之后对结果做一些预处理
(3)可以对请求和响应数据做转换
(4)可以取消请求
(5)可以自动将结果转换为json数据
(6)客户端可以防止XSRF攻击
3.文档: https://github.com/axios/axios
4.安装:
(1)在项目中 常在终端使用命令安装:npm install axios或yarn add axios
(2)bower install axios 还需要在页面中通过script标签对其引入
(3)CDN引入 在script标签的src属性中:src=“https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js”
Axios的基本使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>axios的基本使用</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
</head>
<body>
<div>
<button>GET请求</button>
<button>POST请求</button>
<button>PUT请求</button>
<button>DELETE请求</button>
</div>
<script>
// 获取按钮
const btns = document.querySelectorAll('button')
// 第一个按钮 请求数据
btns[0].onclick = function (){
// 使用axios发送Ajax请求:直接调用axios这个函数 该函数接收一个参数 这个参数是一个对象 该对象中包含一些属性
axios({
// 请求类型
method: 'GET',
url: 'http://localhost:3000/posts/2'// 这里写我们刚用json-server启动的服务的地址
// 还可以设置请求头信息等 此处没设置
}).then(response => {// 因为axios返回的结果是一个promise对象 所以我们可以用then来指定成功的回调
console.log(response)
})
}
// 第二个按钮 添加一条新的数据
btns[1].onclick = function (){
// 使用axios发送Ajax请求:直接调用axios这个函数 该函数接收一个参数 这个参数是一个对象 该对象中包含一些属性
axios({
// 请求类型
method: 'POST',
url: 'http://localhost:3000/posts', // 这里写资源对应的名称
// 设置请求体
data: {
title: '今天天气不错,还挺风和日丽的',
author: '张三'
}
}).then(response => {// 因为axios返回的结果是一个promise对象 所以我们可以用then来指定成功的回调
console.log(response)
})
}
// 第三个按钮 更新数据
btns[2].onclick = function (){
// 使用axios发送Ajax请求:直接调用axios这个函数 该函数接收一个参数 这个参数是一个对象 该对象中包含一些属性
axios({
// 请求类型
method: 'PUT',
url: 'http://localhost:3000/posts/3', // 这里写要更新的资源的地址 要加id
// 设置请求体
data: {
title: '今天天气不错,还挺风和日丽的',
author: '李四'
}
}).then(response => {// 因为axios返回的结果是一个promise对象 所以我们可以用then来指定成功的回调
console.log(response)
})
}
// 第四个按钮 删除数据
btns[3].onclick = function (){
// 使用axios发送Ajax请求:直接调用axios这个函数 该函数接收一个参数 这个参数是一个对象 该对象中包含一些属性
axios({
// 请求类型
method: 'DELETE',
url: 'http://localhost:3000/posts/3', // 这里写要删除的资源的地址 要加id
}).then(response => {// 因为axios返回的结果是一个promise对象 所以我们可以用then来指定成功的回调
console.log(response)
})
}
</script>
</body>
</html>
Axios其他方式发送请求
通过axios提供的方法发送请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>其他方式发送请求</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
</head>
<body>
<div>
<button>GET请求</button>
<button>POST请求</button>
<button>PUT请求</button>
<button>DELETE请求</button>
</div>
<script>
// 获取按钮
const btns = document.querySelectorAll('button')
// 发送get请求
btns[0].onclick = function (){
// 使用axios发送Ajax请求:直接调用axios这个函数 该函数接收一个参数 这个参数是一个对象 该对象中包含一些属性
axios.request({
// 请求类型
method: 'GET',
url: 'http://localhost:3000/comments'// 这里写想要获取的资源的地址
// 还可以设置请求头信息等 此处没设置
}).then(response => {// 因为axios.request返回的结果是一个promise对象 所以我们可以用then来指定成功的回调
console.log(response)
})
}
// 发送post请求
btns[1].onclick = function (){
// 使用axios.post发送post请求:axios.post('url',[{请求体 即数据},其他信息])
axios.post(
'http://localhost:3000/comments',
{
"body": "喜大普奔",
"postId": 2
}).then(response => {// 因为axios.post返回的结果是一个promise对象 所以我们可以用then来指定成功的回调
console.log(response)
})
}
</script>
</body>
</html>
请求响应结果的结构
上一节发送get请求后 控制台的输出内容
1.config:配置对象 包括请求类型 请求url 请求体等
2.data:响应体的结果 是个对象 因为axios自动将服务器返回的结果做了json解析 解析成了一个对象 方便程序员处理结果
3.headers:响应头信息 响应报文包括:响应行 响应头 响应空行 响应体
4.request:原生Ajax请求对象 axios用来发送Ajax请求 而发送Ajax请求就要用到低层的XMLHttpRequest实例对象 request这个属性中保存的就是当前axios在发送请求时 所创建的那个Ajax对象 即XMLHttpRequest实例对象
5.status:响应状态码
6.statusText:响应状态字符串
Axios配置对象详细说明
配置对象指axios/request/get/post等在调用时 他所接收的那个参数对象config
{
// `url` is the server URL that will be used for the request
// 给URL发送请求
url: '/user',
// `method` is the request method to be used when making the request
// 设置请求类型
method: 'get', // default
// `baseURL` will be prepended to `url` unless `url` is absolute.
// It can be convenient to set `baseURL` for an instance of axios to pass relative URLs
// to methods of that instance.
// 设置url的基础结构 我们在前面发送请求时 写了好几次http://localhost:3000
// 我们可以把'http://localhost:3000'配置成baseURL 即baseURL:'http://localhost:3000'
// 在设置url时 只需要设置具体路径就可以了 即url: '/comments'
// axios内部会自动将baseURL和url进行拼接形成最终的URL(http://localhost:3000/comments)
baseURL: 'https://some-domain.com/api/',
// `transformRequest` allows changes to the request data before it is sent to the server
// This is only applicable for request methods 'PUT', 'POST', 'PATCH' and 'DELETE'
// The last function in the array must return a string or an instance of Buffer, ArrayBuffer,
// FormData or Stream
// You may modify the headers object.
// 对请求的数据做预处理 将处理后的结果发送给服务器
transformRequest: [function (data, headers) {
// Do whatever you want to transform the data
return data;
}],
// `transformResponse` allows changes to the response data to be made before
// it is passed to then/catch
// 对响应的结果做一些改变 我们再用自定义的回调处理改变后的结果
transformResponse: [function (data) {
// Do whatever you want to transform the data
return data;
}],
// `headers` are custom headers to be sent
// 设置请求头信息 在某些项目中 进行身份校验时 他要求你在头信息中加入一个特殊的标识
// 然后检验你的请求是否满足条件 此时就可以借助headers对请求头信息进行设置
headers: {'X-Requested-With': 'XMLHttpRequest'},
// `params` are the URL parameters to be sent with the request
// Must be a plain object or a URLSearchParams object
// 设置url参数 axios会把params对象中的数据变成一个参数字符串 缀到url后边 向服务器发送请求
params: {
ID: 12345
},
// `paramsSerializer` is an optional function in charge of serializing `params`
// (e.g. https://www.npmjs.com/package/qs, http://api.jquery.com/jquery.param/)
// 配置参数序列化 对请求的参数做一个序列化 转化成一个字符串 假如你设置了:
// params: {
// ID: 12345
// },
// 默认情况下 会把params转换成http://localhost:3000/comments?ID=12345
// 但是有时 服务器可能要求参数这样传递:http://localhost:3000/comments?ID/12345 或
// http://localhost:3000/comments?ID.12345 这时你就需要在paramsSerializer中设置了
paramsSerializer: function (params) {
return Qs.stringify(params, {arrayFormat: 'brackets'})
},
// `data` is the data to be sent as the request body
// Only applicable for request methods 'PUT', 'POST', 'DELETE , and 'PATCH'
// When no `transformRequest` is set, must be of one of the following types:
// - string, plain object, ArrayBuffer, ArrayBufferView, URLSearchParams
// - Browser only: FormData, File, Blob
// - Node only: Stream, Buffer
// 设置请求体 有两种形式可以设置:对象形式 字符串形式 如果是对象形式 axios会将其转为json格式字符串进行传递 如果是字符串形式 则直接传递
// 对象形式
data: {
firstName: 'Fred'
},
// syntax alternative to send data into the body
// method post
// only the value is sent, not the key
// 字符串形式
data: 'Country=Brasil&City=Belo Horizonte',
// `timeout` specifies the number of milliseconds before the request times out.
// If the request takes longer than `timeout`, the request will be aborted.
// 设置超时时间 如果超过这个时间客户端还没有收到服务器返回的结果 则取消请求 单位毫秒
timeout: 1000, // default is `0` (no timeout)
// `withCredentials` indicates whether or not cross-site Access-Control requests
// should be made using credentials
// 在跨域请求时 设置是否携带cookie true为携带 false为不携带
withCredentials: false, // default
// `adapter` allows custom handling of requests which makes testing easier.
// Return a promise and supply a valid response (see lib/adapters/README.md).
// 设置请求适配器 一种是在浏览器中发送Ajax请求 一种是在node中发送http请求
adapter: function (config) {
/* ... */
},
// `auth` indicates that HTTP Basic auth should be used, and supplies credentials.
// This will set an `Authorization` header, overwriting any existing
// `Authorization` custom headers you have set using `headers`.
// Please note that only HTTP Basic auth is configurable through this parameter.
// For Bearer tokens and such, use `Authorization` custom headers instead.
// 对请求基础验证 设置用户名密码
auth: {
username: 'janedoe',
password: 's00pers3cret'
},
// `responseType` indicates the type of data that the server will respond with
// options are: 'arraybuffer', 'document', 'json', 'text', 'stream'
// browser only: 'blob'
// 设置响应体结果的格式 默认值json
responseType: 'json', // default
// `responseEncoding` indicates encoding to use for decoding responses (Node.js only)
// Note: Ignored for `responseType` of 'stream' or client-side requests
// 响应结果编码 默认utf8
responseEncoding: 'utf8', // default
// `xsrfCookieName` is the name of the cookie to use as a value for xsrf token
// 设置跨站请求标识 设置cookie名字 这是为了保证请求来自我自己的客户端 而不是来自未知的、其他的页面
// 起保护作用 为什么能实现保护作用:服务器在返回结果是会给你返回一个唯一的标识 客户端下次发送请求时
// 需要把这个标识带过去 服务器认了之后 检测没有问题才会给你做响应 为什么能实现保:有一些网站
// 他页面中会加入一些链接 向我们服务器发送请求 如果你不做这个唯一的标识去检验的话
// 可能这个页面发送过来的请求就直接对我们的结果产生了影响 而加上唯一标识后
// 我们的客户端是可以发送请求的 但是其他的网页 他在发送请求时 是没有这个标识的
// 此时就可以有效避免跨站攻击
xsrfCookieName: 'XSRF-TOKEN', // default
// `xsrfHeaderName` is the name of the http header that carries the xsrf token value
// 设置跨站请求标识 设置头信息名字
xsrfHeaderName: 'X-XSRF-TOKEN', // default
// `onUploadProgress` allows handling of progress events for uploads
// browser only
// 设置上传时的回调函数
onUploadProgress: function (progressEvent) {
// Do whatever you want with the native progress event
},
// `onDownloadProgress` allows handling of progress events for downloads
// browser only
// 设置下载时的回调函数
onDownloadProgress: function (progressEvent) {
// Do whatever you want with the native progress event
},
// `maxContentLength` defines the max size of the http response content in bytes allowed in node.js
// 设置HTTP响应体的最大尺寸 单位字节
maxContentLength: 2000,
// `maxBodyLength` (Node only option) defines the max size of the http request content in bytes allowed
// 设置请求体的最大尺寸
maxBodyLength: 2000,
// `validateStatus` defines whether to resolve or reject the promise for a given
// HTTP response status code. If `validateStatus` returns `true` (or is set to `null`
// or `undefined`), the promise will be resolved; otherwise, the promise will be
// rejected.
// 对响应结果的成功来做一个设置 响应状态码status >= 200 && status < 300则认为成功
validateStatus: function (status) {
return status >= 200 && status < 300; // default
},
// `maxRedirects` defines the maximum number of redirects to follow in node.js.
// If set to 0, no redirects will be followed.
// 最大跳转次数 客户端向某一服务器发送请求时 服务器做了跳转 客户端是否继续请求 默认值5
// 客户端跳转5次服务器跟进5次 第6次跳转客户端就不继续请求了 用于node
maxRedirects: 5, // default
// `socketPath` defines a UNIX Socket to be used in node.js.
// e.g. '/var/run/docker.sock' to send requests to the docker daemon.
// Only either `socketPath` or `proxy` can be specified.
// If both are specified, `socketPath` is used.
// 设置socket文件的位置 用于向docker守护进程发送请求 即做数据转发
// 如果你设置了socketPath又设置了proxy 则优先使用socketPath
socketPath: null, // default
// `httpAgent` and `httpsAgent` define a custom agent to be used when performing http
// and https requests, respectively, in node.js. This allows options to be added like
// `keepAlive` that are not enabled by default.
// 设置客户端信息 如keepAlive: true 是否保持链接
httpAgent: new http.Agent({ keepAlive: true }),
httpsAgent: new https.Agent({ keepAlive: true }),
// `proxy` defines the hostname, port, and protocol of the proxy server.
// You can also define your proxy using the conventional `http_proxy` and
// `https_proxy` environment variables. If you are using environment variables
// for your proxy configuration, you can also define a `no_proxy` environment
// variable as a comma-separated list of domains that should not be proxied.
// Use `false` to disable proxies, ignoring environment variables.
// `auth` indicates that HTTP Basic auth should be used to connect to the proxy, and
// supplies credentials.
// This will set an `Proxy-Authorization` header, overwriting any existing
// `Proxy-Authorization` custom headers you have set using `headers`.
// If the proxy server uses HTTPS, then you must set the protocol to `https`.
// 设置代理 用于node 一般在做爬虫时 如果你用一个ip向目标服务器发送请求 抓取数据的话
// 很可能会被别人禁掉你的ip 此时你可以借助中间代理 做上很多代理 疯狂切换 发送请求
// 这样就可以很好的获取目标服务器的数据 包括投票之类的 都用到相同的原理 都用到代理
proxy: {
protocol: 'https',
host: '127.0.0.1',
port: 9000,
auth: {
username: 'mikeymike',
password: 'rapunz3l'
}
},
// `cancelToken` specifies a cancel token that can be used to cancel the request
// (see Cancellation section below for details)
// 对Ajax请求做一个取消的设置
cancelToken: new CancelToken(function (cancel) {
}),
// `decompress` indicates whether or not the response body should be decompressed
// automatically. If set to `true` will also remove the 'content-encoding' header
// from the responses objects of all decompressed responses
// - Node only (XHR cannot turn off decompression)
// 是否解压响应结果 true为解压 默认为true 用于node
decompress: true // default
// transitional options for backward compatibility that may be removed in the newer versions
transitional: {
// silent JSON parsing mode
// `true` - ignore JSON parsing errors and set response.data to null if parsing failed (old behaviour)
// `false` - throw SyntaxError if JSON parsing failed (Note: responseType must be set to 'json')
silentJSONParsing: true; // default value for the current Axios version
// try to parse the response string as JSON even if `resposeType` is not 'json'
forcedJSONParsing: true;
// throw ETIMEDOUT error instead of generic ECONNABORTED on request timeouts
clarifyTimeoutError: false;
}
}
Axios的默认配置
1.可以将重复设置设置在默认设置中 来简化代码
2.通过axios.defaults.上一节提到的config对象中的属性
来设置
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>axios的默认配置</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
</head>
<body>
<div>
<button>GET请求</button>
<button>POST请求</button>
<button>PUT请求</button>
<button>DELETE请求</button>
</div>
<script>
// 获取按钮
const btns = document.querySelectorAll('button')
// 默认配置
axios.defaults.method = 'GET'// 设置默认的请求类型为get
axios.defaults.baseURL = 'http://localhost:3000'// 设置基础url
// axios.default.params = {id: 100}
// axios.default.timeout = 3000
// 发送get请求
btns[0].onclick = function (){
// 使用axios发送Ajax请求:直接调用axios这个函数 该函数接收一个参数 这个参数是一个对象 该对象中包含一些属性
axios({
// method: 'GET',// 请求类型
// url: 'http://localhost:3000/comments'
// 设置了默认配置后 代码简化为:
url: '/comments'// 这里写想要获取的资源的地址
}).then(response => {// 因为axios返回的结果是一个promise对象 所以我们可以用then来指定成功的回调
console.log(response)
})
}
</script>
</body>
</html>
Axios创建示例对象发送Ajax请求
通过axios.create()创建实例对象 这么做的好处/应用场景:假设A服务器 B服务器都提供了数据服务 当我们给A发送请求时 我们需要设置A的协议 域名 端口号 当我们给B发送请求时 我们需要设置B的协议 域名 端口号 如果我们用默认配置去做的话 那么只能使一个有效 但是我们可以通过axios.create()创建两个示例对象 分别给A B两个服务器发送请求 你想给谁发 就调用哪个对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>axios创建示例对象发送Ajax请求</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
</head>
<body>
<button>GET请求</button>
<button>POST请求</button>
<script>
// 获取按钮
const btns = document.querySelectorAll('button')
// 通过axios.create()创建实例对象 axios.create()中接收一个参数 这个参数就是配置对象 在里面可以设置参数
const duanzi = axios.create({
baseURL: 'https://api.apiopen.top',// A服务器的地址
timeout: 2000
})
const B = axios.create({
baseURL: 'https://b.com',// B服务器的地址(这个地址我是瞎写的)
timeout: 2000
})
// 这里axios.create()创建出来的对象duanzi和axios对象功能几乎是一样的
duanzi({
url: '/getJoke'
}).then(response => {
console.log(response)
})
// 也可以利用封装好的方法发送请求
duanzi.get('/getJoke').then(response => {console.log(response.data)})// 为了区分 这里用response.data
</script>
</body>
</html>
Axios拦截器
1拦截器就是一些函数 分为请求拦截器 响应拦截器
2.请求拦截器:在发送请求前 我们可以借助回调函数 来对请求的参数和内容来做一些处理和检测 如果都没有问题 再发送请求 如果有问题 这个请求我们可以停止或取消
3.响应拦截器:当服务器返回结果后 我们可以通过自己的回调来处理结果 响应拦截器可以在我们处理结果前 先对结果做一些预处理 比如 可以对失败的结果做一些提醒或处理 对数据结果做一些格式化的处理 如果每日有问题 再交由我们自己的回调函数来处理 如果有问题 可以直接在响应拦截器中处理掉 我们就可以不用处理了
4.拦截器就像一道道关卡 满足条件就放行(请求拦截器发送请求 响应拦截器将数据交由程序员处理 )如果不满足条件 就进行处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>axios拦截器</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
</head>
<body>
<script>
// 设置请求拦截器
// config就是配置对象 再请求拦截器中 我们可以对config进行处理
axios.interceptors.request.use(function (config) {
console.log('请求拦截器 成功');
// 可以再这里修改config的参数 再请求拦截器中 对请求的参数进行设置
config.params = {a: 100};
return config;
}, function (error) {
console.log('请求拦截器 失败');
return Promise.reject(error);
});
// 设置响应拦截器 response是axios生成的默认的响应结果
axios.interceptors.response.use(function (response) {
console.log('设置响应拦截器 成功');
// 我们可以不处理所有的响应结果 只处理其中的某一个部分 那我们不return response 而return response.data
// 在这里对响应结果进行处理
return response.data;// 只处理响应体
}, function (error) {
console.log('设置响应拦截器 失败');
return Promise.reject(error);
});
axios({
method: 'GET',// 请求类型
url: 'http://localhost:3000/posts'
}).then(response => {// 因为axios返回的结果是一个promise对象 所以我们可以用then来指定成功的回调
console.log('自定义回调处理成功的结果')
}).catch(reject => {
console.log('自定义回调处理失败的结果')
})
// 以上输出:请求拦截器 成功=》设置响应拦截器 成功=》自定义回调处理成功的结果
</script>
<script>
// 设置请求拦截器
axios.interceptors.request.use(function (config) {
console.log('请求拦截器 成功');
throw '参数出错'
}, function (error) {
console.log('请求拦截器 失败');
return Promise.reject(error);
});
// 设置响应拦截器
axios.interceptors.response.use(function (response) {
console.log('设置响应拦截器 成功');
return response;
}, function (error) {
console.log('设置响应拦截器 失败');
return Promise.reject(error);
});
axios({
method: 'GET',// 请求类型
url: 'http://localhost:3000/posts'
}).then(response => {// 因为axios返回的结果是一个promise对象 所以我们可以用then来指定成功的回调
console.log('自定义回调处理成功的结果')
}).catch(reject => {
console.log('自定义回调处理失败的结果')
})
// 以上输出:请求拦截器 成功=》设置响应拦截器 失败=》自定义回调处理失败的结果
</script>
<script>
// 设置请求拦截器
axios.interceptors.request.use(function (config) {
console.log('请求拦截器 成功-1');
return config;
}, function (error) {
console.log('请求拦截器 失败-1');
return Promise.reject(error);
});
axios.interceptors.request.use(function (config) {
console.log('请求拦截器 成功-2');
return config;
}, function (error) {
console.log('请求拦截器 失败-2');
return Promise.reject(error);
});
// 设置响应拦截器
axios.interceptors.response.use(function (response) {
console.log('设置响应拦截器 成功-1');
return response;
}, 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 => {// 因为axios返回的结果是一个promise对象 所以我们可以用then来指定成功的回调
console.log('自定义回调处理成功的结果')
}).catch(reject => {
console.log('自定义回调处理失败的结果')
})
// 以上输出:请求拦截器 成功-2=》请求拦截器 成功-1=》设置响应拦截器 成功-1=》设置响应拦截器 成功-2=》自定义回调处理成功的结果
// 请求拦截器后进先执行 响应拦截器先进先执行
</script>
</body>
</html>
Axios取消请求
让服务器延迟2s再响应json-server --watch db.json -d 2000
或json-server --watch db.json --delay 2000
如果不让服务器延迟响应的话 请求一发出去我们还没取消 就获得了结果 没什么效果
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>取消请求</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
</head>
<body>
<div>
<button>发送请求</button>
<button>取消请求</button>
</div>
<script>
// 获取按钮
const btns = document.querySelectorAll('button')
// 2.声明全局变量
let cancel = null;
// 发送请求
btns[0].onclick = function (){
axios({
method: 'GET',
url: 'http://localhost:3000/comments',
// 取消请求
// 1.添加配置对象的属性
cancelToken: new axios.CancelToken(function executor(c) {
// 3.将c的值赋值给cancel
cancel = c;
})
}).then(response => {// 因为axios返回的结果是一个promise对象
// 所以我们可以用then来指定成功的回调
console.log(response)
// 4.将cancel的值初始化 请求回来之后 将cancel复原 这样你下次发送请求时
// 在请求的过程中(请求未完成) cancel为null
cancel = null
})
}
// 5.绑定第2个事件 取消请求
btns[1].onclick = function (){
cancel();
}
</script>
</body>
</html>
在抢购的时候 用户疯狂点击 疯狂发请求 服务器压力很大 那么我们可以在每次发请求前检测一下是不是正在发请求 如果有 则取消掉 重新发请求 和防抖一个原理
<script>
// 获取按钮
const btns = document.querySelectorAll('button')
// 2.声明全局变量
let cancel = null;
// 发送请求
btns[0].onclick = function (){
// 检测上一次的请求是否已经完成 通过判断cancel的值是不是null来判断请求是否完成
// 因为我们执行完axios后 会将c的值赋值给cancel
if (cancel) {
cancel();// 取消上一次的请求
}
axios({
method: 'GET',
url: 'http://localhost:3000/comments',
// 取消请求
// 1.添加配置对象的属性
cancelToken: new axios.CancelToken(function executor(c) {
// 3.将c的值赋值给cancel
cancel = c;
})
}).then(response => {// 因为axios返回的结果是一个promise对象
// 所以我们可以用then来指定成功的回调
console.log(response)
// 4.将cancel的值初始化 请求回来之后 将cancel复原 这样你下次发送请求时
// 在请求的过程中(请求未完成) cancel为null
cancel = null
})
}
// 5.绑定第2个事件 取消请求
btns[1].onclick = function (){
cancel();
}
</script>
二次封装
一、基本封装需要做哪些
二、在src文件夹下新建axios.js文件,用于基本全局配置、token、密钥、响应的统一基本处理,代码如下:
//配置全局得基础配置
import axios from "axios";// 引入axios
//配置中心
import webConfig from "@/global.config.js"
//base64
import { Base64 } from "js-base64"
import router from "@/router";
//baseURL,timeout,header,responseType,withCredentials
//后面的请求用request来发
let request = axios.create({
//1,基础配置
baseURL: "http://localhost:8000/",
timeout: 30 * 1000,
responseType: "json",
headers: {
"a": "123"
}
})
request.interceptors.request.use((config) => {
//token,密钥得设置
let whiteList = webConfig.whiteListApi
let url = config.url// 本次请求的url
// 假设token存在localStorage里面,先判断一下localStorage里有没有token
let token = localStorage.getItem("token");
if (whiteList.indexOf(url) === -1 && token) {
// 判断本次请求的url是否在白名单里,如果不在,表明本次请求需要token
config.headers.token = token;
}
//密钥-secretId+特殊算法
let _secret = Base64.encode(webConfig.secretId + new Date().toString());
config.headers.secret = _secret;
return config;
}, error => {
return Promise.reject(new Error(error))
})
request.interceptors.response.use((res) => {
//响应得统一处理
const status = res.data.code || 200
const message = res.data.msg || "未知错误";
if (status === 401) {
alert("你没有权限");
router.push("/about")
return Promise.reject(new Error(message));
}
if (status !== 200) {
alert("错误码" + status + " " + message);
return Promise.reject(new Error(message));
}
return res;
}, error => {
//真实项目中,往往使用组件库得消息提示 $waring
alert(error)
return Promise.reject(new Error(error));
})
export default request;
src文件夹下新建global.config.js文件,用于全局配置,具体代码如下:
export default {
whiteListApi: ["/a", "/b"],// 不需要验证token的URL配在这里
secretId: "helloworld",// 加密密钥
pageSize: [20, 40, 80]
}
在src文件夹下新增api文件夹用于封装请求方法,一般项目中都是分模块的,在api文件夹下根据模块新建js文件,比如有用户模块,就新增user.js,有商城模块,就新增shop.js。user.js具体代码如下:
import { request } from "./request"
export const getList = (params) => {
return request({
url: "/getList",
method: "get",
params: {
...params
}
})
}
在vue中使用:
import HelloWorld from '@/components/HelloWorld.vue'
import { getList } from "@/api/user"
export default {
name: 'Home',
components: {
HelloWorld
},
mounted() {
},
methods: {
getList() {
getList().then((res) => {
console.log(res);
})
}
}
}
三、扩展:我们通过发现业务中的一些请求相关的处理时经常重复进行的,不妨把他封装进来,让请求更加简便:
- 防止频繁提交:很多按钮都需要进行防止频繁提交的操作,每次都要写一遍代码很冗余,直接把节流功能封装到request中,
- 缓存数据
在api文件夹下新增request.js用于添加额外功能,具体代码如下:
import request from "@/axios";
let myRequest = (function () {
let mem = {};//Map对象更合适
let hasRequest = [];
return function (config) {
let url = config.url
if (mem[url]) {
// 如果已经有这个接口的缓存数据了,直接返回数据,否则发起请求
return Promise.resolve(mem[url]);
} else {
if (hasRequest.indexOf(url) !== -1) {
return Promise.reject({ mes: "请求已经提交" })
}
hasRequest.push(url);
return request({
...config
}).then((res) => {
hasRequest = hasRequest.filter((item) => {
if (item !== url) {
return item;
}
})
// 缓存数据:每次请求完成,将响应数据保存在mem中
mem[url] = res;
return res
})
}
}
})()
export {
myRequest as request,// 具备扩展功能的request
request as initRequest// 不具备扩展功能的request
}
用法同前述