一. 介绍
1. axios
基于Promise 用于浏览器和 nodejs 的 HTTP 客户端
2. jsonp
- 解决跨域问题
- 原理:通过
<script>
标签的src
属性来帮助请求跨域数据 - 方式:利用
<script>
标签的src
去服务器请求数据,将数据当做一个javascript
的函数来执行,并将请求到的json
数据作为参数 - 核心:监听
winsow
上的jsonp
进行回调时的名称
我的妈…看了好多才觉得理通顺了
简述一下:
客户端:
<!DOCTYPE html>
<html lang="en">
<body>
<div id="mydiv">
<button id="btn" onclick="btnClick">点击</button>
</div>
<script>
function btnCallback(jsonData) {
// 接受数据后的操作
// ...
const body = document.getElementByTagName('body');
const script = document.getElementById('jsonp' + count);
body.removeChild(script);
}
</script>
<script type="text/javascript">
let count = 0;
function btnClick() {
// 创建一个script标签
const script = document.createElement('script');
script.id = "jsonp" + (++count);
// 给script标签的src属性赋值,使其请求第三方服务器
script.src = "https://api.douban.com/v2/book/search?q=javascript&count=1&callback=btnCallback";
const body = document.getElementByTagName('body');
body.appendChild(script);
}
</script>
</body>
</html>
服务端(我是搞java
的,所以使用java
写了,只写方法,当然只是模仿豆瓣的请求):
@RequestMapping("/v2/book/search")
@ResponseBody
public String bookSearch(String q, int count, String callback) {
List<Book> books = new ArrayList<>(count);
for(int i = 0; i < books.size(); i++) {
Book book = new BooK()
.setId(i)
.setName("book" + i)
// ...
.setPrice(i * 10);
}
// Book也实现toString方法
return callback + "(" + books.toString + ")"
}
描述一波:简单的说,jsonp的实质是
欺骗浏览器
前提:浏览器请求js文件时,请求的是文件中的字符,而不是将该文件下载到本地
- 步骤一: 客户端点击按钮, 会创建一个
script
标签,该标签的src
是请求路径,创建之后,浏览器就会向请求路径发送请求.
注意:第一步中的请求实际是一个请求js文件的请求!!!你没有看错
- 步骤二:服务端接受请求,进行数据处理后会返回一个
callback
,其参数就是客户端需要的json
数据,使用字符串拼接出callback(param)
的格式.
注意:第二步的本质是模仿一个js文件,他是拼接出来的,跟项目中的静态js来源不一样,对浏览器来说他们之间没有任何区别!!!你又没有看错
- 步骤三:客户端接受服务端响应的内容(他认为是js文件),它去执行js文件内容,内容告诉它去执行
callback
函数,然后它就傻乎乎的去执行callback
函数.
注意:这里的本质是客户端去执行请求到的js文件(他并不知道这不是一个js文件,而是被拼接出来的),服务端告诉客户端:我这个文件里就一个,去执行callback函数,参数为param!!!你还是没有看错
主学axois
,所以jsonp
只在此处简单介绍使用
二. 使用
1. 基本使用
安装
npm install axios --save
使用
import axios from 'axios';
axios({
url: 'http://httpbin.org/get',
// 不定义默认是get
method: 'get',
params: {
page: 1
}
}).then(res => {
console.log(res)
})
2. 并发请求
// 1.
axios.all(
[
axios(),
axios()
]
).then(res => {
console.log(res[0]);
console.log(res[1]);
})
// 2.
axios.all(
[
axios(),
axios()
]
).then(axios.spread((res1, res2) => {
console.log(res1);
console.log(res2);
}))
3. 全局配置
import axios from "axios";
axios.defaults.baseURL = 'http://httpbin.org'
axios.defaults.timeout = 5000
axios.defaults.responseType = "json"
// ...
export default axios
此时需要配置生效,则使用时导入的不再是axios
包中的实例,而是配置文件中导出的实例
如果项目中的某个请求不想使用全局配置可以新创建实例
- 自创建
// 使用进行了全局配置的axios实例
import axios from './config/axiosConfig'
axios.creat(config);
- 重新导入
axios
实例
// 导入新的axios实例
import axios from 'axios'
4. 封装
以下只做了简单封装,具体怎样封装,你开心就好
import axios from './config/axiosConfig'
const request = {
get: (config) => {
// 预处理
config.method = 'get';
config.responseType = 'json';
// 返回的内容是一个Promise
return axios(config).then((res) => {
return res.data;
});
},
post: (config) => {
// 预处理
config.method = 'post';
config.responseType = 'json';
// 返回的内容是一个Promise
return axios(config).then((res) => {
return res.data;
}).catch((err) => {
return err;
});
},
// ...
}
更详细的还可以封装,如:post
可以封装提交数据是Form
格式还是Json
格式,或者上传的文件等
import request from '../network/request'
export function postData(url, param, body) {
let config = {
url: url,
params: param,
data: body,
// ...
};
return request.post(config);
}
5.拦截器
拦截器可以有全局的拦截器和单个实例的拦截器,此处只描述全局拦截器,单个实例的拦截器在定义实例时用相同方式配置拦截器即可
- 请求拦截(成功和失败)
在请求全局配置文件中添加
axios.interceptors.request.use((config) => {
// config参数就是请求的配置
// ...
// 处理操作
// 最后要把config返回,请求才会继续发送,否则被拦截下来,不再发送请求
return config;
}, (err) => {
})
- 响应拦截(成功和失败)
axios.interceptors.response.use((response) => {
// response是axios封装后的服务器结果
// 其中的data就是服务器响应的内容
// 如果直接返回response.data,则之前封装的axios请求就直接return res即可
return response.data
}, (err) => {
})
上述配置中的use
的参数中,第一个参数是成功时的回调函数,第二个参数时失败时的回调函数
日 期 : 2021 − 12 − 05 \color{#00FF00}{日期:2021-12-05} 日期:2021−12−05