1 基础概念
1.1 接口调用的方式
- 原生 ajax
- 基于 jQuery 的ajax
- fetch
- axios
1.2 URL格式
格式:schema://host:port/path?query#fragment
① schema:协议。例如http、https、ftp等
② host:域名或者IP地址
③ port:端口, http默认端口80,可以省略
④ path:路径, 例如/abc/a/b/c
⑤ query :查询参数,例如 uname=lisi&age=12
⑥ fragment :锚点(哈希Hash),用于定位页面的某个位置
Restful: http://www.hello.com/books/123
1.3 http请求方式
① GET 查询
② POST 添加
③ PUT 修改
④ DELETE 删除
2 异步解决方案 Promise
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
异步:
① 定时任务
② Ajax
③ 事件函数
2.1 传统多次异步调用依赖产生问题—回调地狱
异步调用结果如果存在依赖需要嵌套,依赖就是需要顺序输出。
$.ajax({
success: function (data) {
if (data.status == 200) {
$.ajax({
success: function (data) {
if (data.status == 200) {
$.ajax({
success: function (data) {
if (data.status == 200) { }
}
});
}
}
});
}
}
});
2.2 Promise基本用法
Promise 是异步编程的一种解决方案。
类型是函数。也是一个对象,可以获取异步操作的消息。
它提供了简洁的API,使得控制异步操作更加容易。
- resolve 和 reject 两个参数用于处理成功和失败两种情况,
- 当异步任务顺利完成且返回结果值时,会调用 resolve 函数;而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用reject 函数,并通过 p.then 获取处理结果
案例: ```javascript var p = new Promise(function (resolve, reject) { setTimeout(function () { var flag = true; flag ? resolve(‘nice’) : reject(‘err,hehehe’) }) });var p = new Promise(function(resolve, reject){
// 成功时调用 resolve()
// 失败时调用 reject()
});
p.then(function(ret){
// 从resolve得到正常结果
}, function(ret){
// 从reject得到错误信息
});
p.then(ok => { console.log(ok) }, err => { console.log(err) })
![image.png](https://cdn.nlark.com/yuque/0/2021/png/1688721/1625290651720-046d07cf-1bc0-42b2-89bd-f5ce13699002.png#height=51&id=bIs04&margin=%5Bobject%20Object%5D&name=image.png&originHeight=102&originWidth=708&originalType=binary&ratio=1&size=3076&status=done&style=none&width=354)
<a name="vHRDd"></a>
## 2.3 封装ajax,发送多个请求
单次调用
```javascript
function queryDate(url) {
var p = new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
if (xhr.readyState != 4) return;
if (xhr.readyState == 4 && xhr.status == 200) {
resolve(xhr.responseText);
} else {
reject('服务器异常');
}
}
xhr.open('get', url);
xhr.send(null);
})
return p
}
queryDate('http://localhost:3000/data')
.then(function (data) {
console.log(data);
}, function (info) {
console.log(info);
})
多次调用:
queryDate('http://localhost:3000/data')
.then(function (data) {
console.log(data);
return queryDate('http://localhost:3000/data1');
}).then(function (data) {
console.log(data);
return queryDate('http://localhost:3000/data2');
}).then(function (data) {
console.log(data);
})
通过返回Promise实例对象,调用下一个then,变成链式从而解决回调地狱。
2.4 then参数的函数返回值
若是返回一个普通值,这个也会产生一个默认的Promise对象继续可以使用then,通过 then 参数中函数的参数接收该值。
queryDate('http://localhost:3000/data')
.then(function (data) {
console.log(data);
return "helloworld";
}).then(data => {
console.log(data);
})
2.5 Promise实例方法
- p.then() 得到异步任务的正确结果
- p.catch() 获取异常信息
- p.finally() 成功与否都会执行(尚且不是正式标准)
function foo() {
return new Promise(function(resolve, reject) {
setTimeout(function(){
reject('err')
}, 100);
});
}
foo().then(data => {
console.log(data);
}).catch( err=>{
console.log(err);
}).finally(function() {
console.log('finish end');
})
foo().then(data => {
console.log(data);
}).catch( err=>{
console.log(err);
})
等价于
foo().then(data => {
console.log(data);
},err=>{
console.log(err);
})
2.6 Promise对象方法
- Promise.all() 并发处理多个异步任务,所有任务都执行完成才能得到结果
- Promise.race() 并发处理多个异步任务,只要有一个任务完成就能得到结果
```javascript
function queryDate(url) {
var p = new Promise(function (resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
} xhr.open(‘get’, url); xhr.send(null); }) return p; }if (xhr.readyState != 4) return;
if (xhr.readyState == 4 && xhr.status == 200) {
resolve(xhr.responseText);
} else {
reject('服务器异常');
}
var p1 = queryDate(‘http://localhost:3000/a1‘); var p2 = queryDate(‘http://localhost:3000/a2‘); var p3 = queryDate(‘http://localhost:3000/a3‘); Promise.all([p1, p2, p3]).then(result => { console.log(result); }); Promise.race([p1, p2, p3]).then(result => { console.log(result); });
![image.png](https://cdn.nlark.com/yuque/0/2021/png/1688721/1625297953566-af6a57d8-a8f1-4a57-8192-2b613e0ad412.png#height=75&id=AMrOv&margin=%5Bobject%20Object%5D&name=image.png&originHeight=150&originWidth=954&originalType=binary&ratio=1&size=14623&status=done&style=none&width=477)
<a name="XrNQl"></a>
# 3 fetch
[https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API)<br />更加简单的数据获取方式,功能更强大、更灵活,可以看做是xhr的升级版<br />基于Promise实现
<a name="YpY5d"></a>
## 3.1 基本使用
常用配置选项
- method(String): HTTP请求方法,默认为GET (GET、POST、PUT、DELETE)
- body(String): HTTP的请求参数
- headers(Object): HTTP的请求头,默认为{}
默认请求方式是get
```javascript
fetch('http://localhost:3000/fdata').then(function(data){
console.log(data);
// text()方法属于fetchAPI一部分,返回一个Promise实例对象,用于获取后台返回数据
return data.text();
}).then(function(data){
// 注意这里得到的才是最终的数据
console.log(data);
});
3.2 delete请求方式
fetch('/abc/123', {
method: 'delete'
}).then(data => {
return data.text();
}).then(ret => {
// 注意这里得到的才是最终的数据
console.log(ret);
});
3.3 post请求方式
fetch('http://localhost:3000/books', {
method: 'post',
body: 'uname=lisi&pwd=123',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
}
}).then(data => {
return data.text();
}).then(ret => {
console.log(ret);
});
3.4 put请求方式
fetch('http://localhost:3000/books/123', {
method: 'PUT',
body: JSON.stringify({
uname: '张三',
pwd: '789'
}),
headers: {
'Content-Type': 'application/json'
}
})
.then(function(data){
return data.text();
}).then(function(data){
console.log(data)
});
3.5 返回JSON格式数据
响应数据格式
- text(): 将返回体处理成字符串类型
- json():返回结果和 JSON.parse(responseText)一样
fetch('/abc' then(data=>{
// return data.text();
return data.json();
}).then(ret=>{
console.log(ret);
});
4 axios
它的底层也是封装xhr
axios(官网:https://github.com/axios/axios)
是一个基于Promise 用于浏览器和 node.js 的 HTTP 客户端。
- 支持浏览器和 node.js
- 支持 promise
- 能拦截请求和响应
- 自动转换 JSON 数据
4.1 基本用法
data属性名称是固定的,用于获取后台响应的数据axios.get('http://localhost:3000/adata').then(el => {
console.log(el.data);
})
4.2 get带参数请求
```javascript axios.get(‘/adata?id=123’).then(ret=>{
})console.log(ret.data)
axios.get(‘/adata/123’).then(ret=>{ console.log(ret.data) })
axios.get(‘/adata’,{ params: { id: 123 } }).then(ret=>{ console.log(ret.data) })
<a name="03KfE"></a>
## 4.3 delete
```javascript
axios.delete('/adata?id=123').then(ret=>{
console.log(ret.data)
});
axios.delete('/adata/123').then(ret=>{
console.log(ret.data)
});
axios.delete(‘/adata‘,{params: {id: 123}}).then(ret=>{
console.log(ret.data)
})
4.4 post
默认传递的是 json 格式的数据
axios.post('/adata',{
uname: 'tom',
pwd: 123
}).then(ret=>{
console.log(ret.data)
})
通过 URLSearchParams 传递参数(application/x-www-form-urlencoded)**URLSearchParams**
接口定义了一些实用的方法来处理 URL 的查询字符串[URLSearchParams.append()](https://developer.mozilla.org/zh-CN/docs/Web/API/URLSearchParams/append)
插入一个指定的键/值对作为新的搜索参数。
const params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/api/test', params).then(ret=>{
console.log(ret.data)
})
4.5 put
axios.put(‘/adata/123',{
uname: 'tom',
pwd: 123
}).then(ret=>{
console.log(ret.data)
})
4.6 axios 的响应结果
响应结果的主要属性
- data : 实际响应回来的数据
- headers :响应头信息
- status :响应状态码
- statusText :响应状态信息
axios.post('/axios-json').then(ret=>{
console.log(ret)
})
4.7 全局配置
axios.defaults.timeout = 3000; // 超时时间
axios.defaults.baseURL = 'http://localhost:3000/app'; // 默认地址
axios.defaults.headers['mytoken'] = 'aqwerwqwerqwer2ewrwe23eresdf23’// 设置请求头
4.8 axios拦截器请求拦截器
//添加一个请求拦截器
axios.interceptors.request.use(function(config){
//在请求发出之前进行一些信息设置
return config;
},function(err){
// 处理响应的错误信息
});
4.9 响应拦截器
//添加一个响应拦截器
axios.interceptors.response.use(function(res){
//在这里对返回的数据进行处理
return res;
},function(err){
// 处理响应的错误信息
})
案例:
axios.interceptors.request.use(function(config) {
console.log(config.url)
config.headers.mytoken = 'nihao';
return config;
}, function(err){
console.log(err)
})
axios.interceptors.response.use(function(res) {
var data = res.data;
return data;
}, function(err){
console.log(err)
})
axios.get('http://localhost:3000/adata').then(function(data){
console.log(data)
})
5 async/await
- async/await是ES7引入的新语法,可以更加方便的进行异步操作
- async 关键字用于函数上(async函数的返回值是Promise实例对象)
await 关键字用于 async 函数当中(await可以得到异步的结果)
5.1 基本使用
async function queryData(id) {
const ret = await axios.get('/data');
return ret;
}
queryData.then(ret=>{
console.log(ret)
})
使用案例:
deleteBook: async function (i) {
var val = await axios.delete('books/' + i);
val.status == 200 && this.queryDate();
},
因为async函数的返回值是Promise实例对象
- await 右侧的表达式一般为 promise 对象
- await 返回的是 promise 成功的值
- await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
5.2 多个异步请求
async function queryData(id) {
const info = await axios.get('/async1');
const ret = await axios.get(‘async2?info=‘+info.data);
return ret;
}
queryData.then(ret=>{
console.log(ret)
})
5.3 使用then和不使用then
两个console.log()值都一样
async function getList() {
var url = 'http://www.liulongbin.top:3006/api/get'
// 请求的参数对象
var paramsObj = { name: 'zs', age: 20 }
const result = await axios.get(url, { params: paramsObj })
console.log(result);
return result
}
getList().then(ret => {
console.log(ret)
})