1. JSON Server
支持跨域
1. 安装 JSON 服务器
npm install -g json-server
2. 创建db.json文件,复制下面内容
{
"posts": [
{ "id": 1, "title": "json-server", "author": "typicode" }
],
"comments": [
{ "id": 1, "body": "some comment", "postId": 1 }
],
"profile": { "name": "typicode" }
}
3. 启动 JSON 服务器,注意要在db.json文件所在的文件夹下启动终端
json-server --watch db.json
2. axios
2.1. axios 是什么?
- 前端最流行的 ajax 请求库
- react/vue 官方都推荐使用 axios 发 ajax 请求
- axios速查表
2.2. axios 特点
- 基于 xhr + promise 的异步 ajax 请求库
- 浏览器端/node 端都可以使用
- 支持请求/响应拦截器
- 支持请求取消
- 请求/响应数据转换
- 批量发送多个请求
2.3 直接使用axios发起请求
axios的基本使用
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>axios基本使用</title>
<link crossorigin="anonymous" href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css"
rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
</head>
<body>
<div class="container">
<h2 class="page-header">基本使用</h2>
<button class="btn btn-primary"> 发送GET请求 </button>
<button class="btn btn-warning"> 发送POST请求 </button>
<button class="btn btn-success"> 发送 PUT 请求 </button>
<button class="btn btn-danger"> 发送 DELETE 请求 </button>
</div>
<script>
//获取按钮
const btns = document.querySelectorAll('button');
//第一个
btns[0].onclick = function () {
//发送 AJAX 请求
axios({
//请求类型
method: 'GET',
//URL
// url: 'http://localhost:3000/posts?id=2',
url: 'http://localhost:3000/posts/2',
//得到一个db.json中id=2的对象
}).then(response => {
console.log(response);
});
}
//添加一篇新的文章
btns[1].onclick = function () {
//发送 AJAX 请求
axios({
//请求类型
method: 'POST',
//URL
url: 'http://localhost:3000/posts',
//设置请求体
data: {
//将data中的数据发送到对应的服务器
title: "今天天气不错, 还挺风和日丽的",
author: "张三"
}
}).then(response => {
console.log(response);
});
}
//更新数据
btns[2].onclick = function () {
//发送 AJAX 请求
axios({
//请求类型
method: 'PUT',
//URL
url: 'http://localhost:3000/posts/3',
//设置请求体
data: {
//将data中的数据更新到对应的服务器的相应路径
title: "今天天气不错, 还挺风和日丽的",
author: "李四"
}
}).then(response => {
console.log(response);
});
}
//删除数据
btns[3].onclick = function () {
//发送 AJAX 请求
axios({
//请求类型
method: 'delete',
//URL
url: 'http://localhost:3000/posts/3',
//删除对应路径中的数据
}).then(response => {
console.log(response);
});
}
</script>
</body>
</html>
db.json虚拟哦服务器
{
"posts": [
{
"id": 1,
"title": "json-server",
"author": "typicode"
},
{
"id": 2,
"title": "尚硅谷大厂学院上线啦",
"author": "小编"
}
],
"comments": [
{
"id": 1,
"body": "some comment",
"postId": 1
},
{
"body": "喜大普奔",
"postId": 2,
"id": 2
}
],
"profile": {
"name": "typicode"
}
}
2.4 axios 常用语法
-
axios(config): 通用/最本质的发任意类型请求的方式
-
axios(url[, config]): 可以只指定 url 发 get 请求
-
axios.request(config): 等同于 axios(config)
-
axios.get(url[, config]): 发 get 请求
-
axios.delete(url[, config]): 发 delete 请求
-
axios.post(url[, data, config]): 发 post 请求
-
axios.put(url[, data, config]): 发 put 请求
-
axios.defaults.xxx: 请求的默认全局配置
-
axios.interceptors.request.use(): 添加请求拦截器
-
axios.interceptors.response.use(): 添加响应拦截器
-
axios.create([config]): 创建一个新的 axios(它没有下面的功能)
-
axios.Cancel(): 用于创建取消请求的错误对象
-
axios.CancelToken(): 用于创建取消请求的 token 对象
-
axios.isCancel(): 是否是一个取消请求的错误
-
axios.all(promises): 用于批量执行多个异步请求
-
axios.spread(): 用来指定接收所有成功数据的回调函数的方法
axios路径
/**下方路径都是相等的
* axios({
* url: '/post',
* // /post?a=100&b=200
* // /post/a/100/b/200
* // /post/a.100/b.200
* params: {
* a:100,
* b:200
* }
* })
*/
2.5 axios语法发起请求
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div>
<button onclick="testGet()">GET请求</button>
<button onclick="testPost()">POST请求</button>
<button onclick="testPut()">PUT请求</button>
<button onclick="testDelete()">DELETE请求</button>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.js"></script>
<script>
function testGet() {
axios.get('http://localhost:3000/posts') // 返回一个数组,数组里有两个对象
// axios.get('http://localhost:3000/posts/1') // 返回一个对象
// axios.get('http://localhost:3000/posts?id=1') // 返回一个数组,数组里有一个对象
.then(response => {
console.log('/posts get', response.data)
})
}
function testPost() { // 添加数据
axios.post('http://localhost:3000/posts',
{
"title": "json-server3", "author": "typicode"
})
.then(response => {
console.log('/posts put', response.data)
})
}
function testPut() { // 更新数据
axios.put('http://localhost:3000/posts/3',
{
"title": "json-server_put", "author": "typicode"
})
.then(response => {
console.log('/posts post', response.data)
})
}
function testDelete() { // 删除数据
axios.delete('http://localhost:3000/posts/3')
.then(response => {
console.log('/posts delete', response.data)
})
}
</script>
</body>
</html>
2.6 axios全局(默认)配置
<script>
//获取按钮
const btns = document.querySelectorAll('button');
//默认配置
axios.defaults.method = 'GET';//设置默认的请求类型为 GET
axios.defaults.baseURL = 'http://localhost:3000';//设置基础 URL
axios.defaults.params = { id: 2 };//配置默认参数
axios.defaults.timeout = 3000;//超时设置
btns[0].onclick = function () {
axios({
url: '/posts'
}).then(response => {
console.log(response);
})
}
</script>
3. 难点语法的理解和使用
3.1 axios.create(config)
-
根据指定配置创建一个新的 axios, 也就是每个新 axios 都有自己的配置
-
新 axios 只是没有取消请求和批量发请求的方法, 其它所有语法都是一致的
为什么要设计这个语法?
- 需求: 项目中有部分接口需要的配置与另一部分接口需要的配置不太一样, 如何处理(比如有多个baseURL需要指定)
- 解决: 创建2 个新axios, 每个都有自己特有的配置, 分别应用到不同要求的接口请求中
const instance = axios.create({ // instance是函数类型
baseURL: 'http://localhost:3000'
})
// 使用instance发Ajax请求
instance({
url: '/posts'
})
instance.get('/posts')
创建实例
<script>
//创建实例对象 /getJoke
const duanzi = axios.create({
baseURL: 'https://api.apiopen.top',
timeout: 2000
});
const another = axios.create({
baseURL: 'https://b.com',
timeout: 2000
});
//这里 duanzi 与 axios 对象的功能几近是一样的
// duanzi({
// url: '/getJoke',
// }).then(response => {
// console.log(response);
// });
duanzi.get('/getJoke').then(response => {
console.log(response.data)
})
</script>
3.2 拦截器函数/ajax 请求/请求的回调函数的调用顺序
- 说明: 调用axios()并不是立即发送ajax 请求, 而是需要经历一个较长的流程
- 流程: 请求拦截器2 => 请求拦截器1 => 发ajax 请求 => 响应拦截器1 => 响应拦截器2 => 请求的回调
- 注意: 此流程是通过 promise 串连起来的, 请求拦截器传递的是config, 响应拦截器传递的是response
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>拦截器</title>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
</head>
<body>
<script>
// Promise
// 设置请求拦截器 config 配置对象
axios.interceptors.request.use(function (config) {
console.log('请求拦截器 成功 - 1号');
//修改 config 中的参数
config.params = { a: 100 };
// throw '失败'
return config;
}, function (error) {
console.log('请求拦截器 失败 - 1号');
return Promise.reject(error);
});
axios.interceptors.request.use(function (config) {
console.log('请求拦截器 成功 - 2号');
//修改 config 中的参数
config.timeout = 2000;
return config;
}, function (error) {
console.log('请求拦截器 失败 - 2号');
return Promise.reject(error);
});
// 设置响应拦截器
axios.interceptors.response.use(function (response) {
console.log('响应拦截器 成功 1号');
// 查看响应状态信息
console.log(response);
return response;
}, function (error) {
console.log('响应拦截器 失败 1号')
return Promise.reject(error);
});
axios.interceptors.response.use(function (response) {
console.log('响应拦截器 成功 2号')
// 可以对响应结果做一些处理
console.log(response.data);
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);
});
</script>
</body>
</html>
3.3 取消请求
1. 基本流程
- 配置
cancelToken对象 - 缓存用于取消请求的
cancel函数 - 在后面特定时机调用
cancel函数取消请求 - 在错误回调中判断如果
error是cancel, 做相应处理
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>取消请求</title>
<link crossorigin='anonymous' href="https://cdn.bootcss.com/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.21.1/axios.min.js"></script>
</head>
<body>
<div class="container">
<h2 class="page-header">axios取消请求</h2>
<button class="btn btn-primary"> 发送请求 </button>
<button class="btn btn-warning" > 取消请求 </button>
</div>
<script>
//获取按钮
const btns = document.querySelectorAll('button');
//2.声明全局变量
let cancel = null;
//发送请求
btns[0].onclick = function(){
//检测上一次的请求是否已经完成
if(cancel !== null){
//取消上一次的请求
cancel();
}
axios({
method: 'GET',
url: 'http://localhost:3000/posts',
//1. 添加配置对象的属性
cancelToken: new axios.CancelToken(function(c){
//3. 将 c 的值赋值给 cancel
cancel = c;
})
}).then(response => {
console.log(response);
//将 cancel 的值初始化
cancel = null;
})
}
//绑定第二个事件取消请求
btns[1].onclick = function(){
cancel();
}
</script>
</body>
</html>