一. 前后端交互模式
1.1 接口调用方式
- 原生 ajax
- 基于 jQuery 的ajax
- fetch
- axios
1.2 URL 地址格式
1. 传统形式的 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),用于定位页面的某个位置
-
符合规则的URL
①http://www.duanxx.cn
②http://www.duanxx.cn/java/web
③http://www.duanxx.cn/java/web?flag=1
④http://www.duanxx.cn/java/web?flag=1#function
2. Restful 形式的 URL
-
HTTP请求方式
① GET 查询
② POST 添加
③ PUT 修改
④ DELETE 删除
-
符合规则的URL地址
① http://www.hello.com/books GET
② http://www.hello.com/books POST
③ http://www.hello.com/books/123 PUT
④ http://www.hello.com/books/123 DELETE
二. Promise 用法
2.1 异步调用
-
异步效果分析
①定时任务
②Ajax
③事件函数
-
多次异步调用的依赖分析
① 多次异步调用的结果顺序不确定
② 异步调用结果如果存在依赖需要嵌套
缺点:
形成 回调地狱 。
$.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 是异步编程的一种解决方案,从语法上讲,Promise是一个对象,从它可以获取异步操作的消息。
使用 Promise 主要有以下好处:
- 可以避免多层异步调用嵌套问题(回调地狱)
- Promise 对象提供了简洁的API,使得控制异步操作更加容易
官方描述:点击这里 ——> Promise
2.3 Promise 基本用法
- 实例化 Promise 对象,构造函数中传递函数,该函数中用于处理异步任务
- resolve 和 reject 两个参数用于处理成功和失败两种情况,并通过 p.then 获取处理结果
语法结构:
var p = new Promise(function(resolve, reject){
// 成功时调用 resolve()
// 失败时调用 reject()
});
p.then(funciton(ret){
// 从resolve得到正常结果
}, function(ret){
// 从reject得到错误信息
});
案例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>promise基本用法</title>
</head>
<body>
<script type="text/javascript">
var p = new Promise(function(resolve, reject) {
// 这里用于实现异步任务
setTimeout(function() {
var flag = false;
if (flag) {
// 正常情况
resolve("Hello Promise");
} else {
reject('Error ! ! !');
}
}, 1000);
});
p.then(function(data) {
console.log(data);
}, function(info) {
console.log(info);
});
</script>
</body>
</html>
2.4 基于Promise处理Ajax请求
1. 处理原生Ajax
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise处理原生Ajax请求</title>
</head>
<body>
<script type="text/javascript">
function queryData(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;
}
// 单次调用
// queryData('http://localhost:3000/data')
// .then(function(data) {
// console.log(data);
// }, function(info) {
// console.log(info);
// });
// 多次调用
queryData('http://localhost:3000/data')
.then(function(data) {
console.log(data);
return queryData('http://localhost:3000/data1');
})
.then(function(data) {
console.log(data);
return queryData('http://localhost:3000/data2');
})
.then(function(data) {
console.log(data);
});
</script>
</body>
</html>
2.5 then参数中的函数返回值
1. 返回 Promise 实例对象
- 返回的该实例对象会调用下一个 then
2. 返回普通值
- 返回的普通值会直接传递给下一个 then,通过 then 参数中函数的参数接收该值
- 如果上一个then返回普通值,它会默认生成一个Promise实例对象,这是为了保证继续链式操作
案例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>then参数中的返回值</title>
</head>
<body>
<script type="text/javascript">
function queryData(url) {
return 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);
});
}
queryData('http://localhost:3000/data')
.then(function(data) {
queryData('http://localhost:3000/data1');
})
.then(function(data) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(123);
}, 1000);
});
})
.then(function(data) {
// console.log(data) // 结果:123
return 'Hello Little Dragon Boy!'
})
.then(function(data) {
console.log(data);
})
</script>
</body>
</html>
2.6 Promise常用的API
1. 实例方法
- p.then() 得到异步任务的正确结果
- p.catch() 获取异常信息
- p.finally() 成功与否都会执行(尚且不是正式标准)
案例:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Promise中常用API</title>
</head>
<body>
<script type="text/javascript">
function foo() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('Good Promise!');
// reject('Error ! ! !');
}, 100);
});
};
foo()
.then(function(data) {
console.log(data);
})
.catch(function(data) {
console.log(data);
})
.finally(function() {
console.log('finished!');
});
</script>
</body>
</html>
2. 对象方法
- Promise.all() 并发处理多个异步任务,所有任务都执行完成才能得到结果
- Promise.race() 并发处理多个异步任务,只要有一个任务完成就能得到结果
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>常用API对象方法</title>
</head>
<body>
<script type="text/javascript">
function queryData(url) {
return 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);
});
};
var p1 = queryData('http://localhost:3000/a1');
var p2 = queryData('http://localhost:3000/a2');
var p3 = queryData('http://localhost:3000/a3');
// Promise.all([p1, p2, p3]).then(function(result) {
// console.log(result);
// });
Promise.race([p1, p2, p3]).then(function(result) {
console.log(result);
});
</script>
</body>
</html>
三. 接口调用-fetch用法
3.1 fetch 概述
1. 基本特性
- 更加简单的数据获取方式,功能更强大、更灵活,可以看做是xhr的升级版
- 基于Promise实现
2. 语法结构
fetch(url).then(fn2)
.then(fn3)
...
.catch(fn)
官方描述:点击这里 ——> Fetch API
3.2 fetch 的基本用法
fetch('/abc').then(data=>{
// text()方法属于 Fetch API 的一部分,它返回一个 Promise 实例对象,用于获取后台返回的数据
return data.text();
}).then(ret=>{
// 注意这里得到的才是最终的数据
console.log(ret);
});
3.3 fetch请求参数
1. 常用配置选项
- method(String): HTTP请求方法,默认为GET (GET、POST、PUT、DELETE)
- body(String): HTTP的请求参数
- headers(Object): HTTP的请求头,默认为{}
2. GET请求方式的参数传递
// 方法1
fetch('http://localhost:3000/books?id=123', {
method: 'get',
}).then(function(data) {
return data.text();
}).then(function(data) {
console.log(data);
});
// ---------------------------------------------
app.get('/books', (req, res) => {
res.send('传统 url 参数传递!' + req.query.id);
});
// 方法2
fetch('http://localhost:3000/books/456', {
method: 'get',
}).then(function(data) {
return data.text();
}).then(function(data) {
console.log(data);
});
// ---------------------------------------------
app.get('/books/:id', (req, res) => {
res.send('Restful 形式的 url 传递参数!' + req.params.id)
});
3. DELETE请求方式的参数传递
另一种方法同上。
fetch('http://localhost:3000/books/789', {
method: 'delete',
}).then(function(data) {
return data.text();
}).then(function(data) {
console.log(data);
});
// ---------------------------------------------
app.delete('/books/:id', (req, res) => {
res.send('delete 传递参数!' + req.params.id);
});
4 POST请求方式的参数传递
fetch('http://localhost:3000/books/987', {
method: 'put',
body: 'uname=段仙子&pwd=123',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).then(function(data) {
return data.text();
}).then(function(data) {
console.log(data);
});
// ---------------------------------------------
app.post('/books', (req, res) => {
res.send('post 传递参数!' + req.body.uname + '----' + req.body.pwd);
});
5. PUT请求方式的参数传递
fetch('http://localhost:3000/books/987', {
method: 'put',
body: JSON.stringify({
uname: '段仙子',
pwd: '20',
}),
headers: {
'Content-Type': 'application/json'
}
}).then(function(data) {
return data.text();
}).then(function(data) {
console.log(data);
});
// ---------------------------------------------
app.put('/books/:id', (req, res) => {
res.send('put 传递参数!' + req.params.id + '----' + req.body.uname + '----' + req.body.pwd);
});
3.4 fetch响应结果
响应数据格式
- text(): 将返回体处理成字符串类型
- json():返回结果和 JSON.parse(responseText)一样
fetch('http://localhost:3000/json', {
method: 'get',
}).then(function(data) {
return data.json();
}).then(function(data) {
console.log(data);
})
//-----------------------------------------------------
fetch('http://localhost:3000/json', {
method: 'get',
}).then(function(data) {
return data.text();
}).then(function(data) {
console.log(data);
})
四. 接口调用-axios用法
4.1 axios 的基本特性
axios 是一个基于Promise 用于浏览器和 node.js 的 HTTP 客户端。
它具有以下特征:
- 支持浏览器和 node.js
- 支持 promise
- 能拦截请求和响应
- 自动转换 JSON 数据
4.2 axios 的基本用法
<body>
<script src="./js/axios.js"></script>
<script type="text/javascript">
axios.get('http://localhost:3000/adata').then(function(ret) {
console.log(ret);
// data 属性是固定用法,用于获取后台的实际数据。
// console.log(ret.data);
})
</script>
</body>
4.3 axios 的常用API
- get : 查询数据
- post : 添加数据
- put : 修改数据
- delete :删除数据
4.4 axios 的参数传递
1. GET传递参数
-
通过 URL 传递参数
axios.get('http://localhost:3000/axios?id=111').then(function(ret) { console.log(ret.data); }); axios.get('http://localhost:3000/axios/222').then(function(ret) { console.log(ret.data); });
-
通过 params 选项传递参数
// 在前端中,如果使用parms传参,后台获取参数的方法要用 req.query // parms 是 axios专门提供的。 axios.get('http://localhost:3000/axios', { params: { id: 999 } }).then(function(ret) { console.log(ret.data); });
2. DELETE传递参数
-
通过 URL 传递参数
axios.delete('http://localhost:3000/axios?id=111').then(function(ret) { console.log(ret.data); }); axios.delete('http://localhost:3000/axios/222').then(function(ret) { console.log(ret.data); });
-
通过 params 选项传递参数\
axios.delete('http://localhost:3000/axios', { params: { id: 123 } }).then(function(ret) { console.log(ret.data); });
3. POST传递参数
-
通过选项传递参数(默认传递的是 json 格式的数据)
axios.post('http://localhost:3000/axios', { uname: '段仙子', age: 18 }).then(function(ret) { console.log(ret.data); });
-
通过 URLSearchParams 传递参数(application/x-www-form-urlencoded)
const params = new URLSearchParams(); params.append('uname', '段小小'); params.append('age', '20'); axios.post('http://localhost:3000/axios', params).then(function(ret) { console.log(ret.data); });
4. PUT传递参数
-
通过选项传递参数(默认传递的是 json 格式的数据)
axios.put('http://localhost:3000/axios', { uname: '段仙子', age: 99 }).then(function(ret) { console.log(ret.data); });
-
通过 URLSearchParams 传递参数(application/x-www-form-urlencoded)
const params = new URLSearchParams(); params.append('uname', '小小段'); params.append('age', '21'); axios.put('http://localhost:3000/axios', params).then(function(ret) { console.log(ret.data); });
4.5 axios 的响应结果
响应结果的主要属性
- data : 实际响应回来的数据
- headers :响应头信息
- status :响应状态码
- statusText :响应状态信息
4.6 axios 的全局配置
<body>
<script src="./js/axios.js"></script>
<script type="text/javascript">
// 超时时间
axios.defaults.timeout = 3000;
// 配置请求的基准 URL 地址
axios.defaults.baseURL = 'http://localhost:3000';
// 设置请求头
axios.defaults.headers['mytoken'] = 'duanxiaoxioa ^_^';
axios.get('/axios-json').then(function(ret) {
console.log(ret.data.uname);
})
</script>
</body>
4.7 axios拦截器
1. 请求拦截器
在请求发出之前设置一些信息
2. 响应拦截器
在获取数据之前对数据做一些加工处理
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>请求拦截器</title>
</head>
<body>
<script src="./js/axios.js"></script>
<script type="text/javascript">
axios.defaults.baseURL = 'http://localhost:3000';
// 请求拦截器
axios.interceptors.request.use(function(config) {
//在请求发出之前进行一些信息设置
console.log(config.url);
config.headers['mytoken'] = 'good!';
return config
}, function(err) {
// 处理响应的错误信息
console.log(err);
});
// 相应拦截器
axios.interceptors.response.use(function(res) {
//在这里对返回的数据进行处理
// console.log(res)
var data = res.data;
return data;
}, function(err) {
// 处理响应的错误信息
console.log(err);
});
axios.get('/adata').then(res => {
console.log(res);
})
</script>
</body>
</html>
五.接口调用-async/await用法
5.1 async/await 的基本用法
- async/await是ES7引入的新语法,可以更加方便的进行异步操作
- async 关键字用于函数上(async函数的返回值是Promise实例对象)
- await 关键字用于 async 函数当中(await可以得到异步的结果)
<script type="text/javascript">
axios.defaults.baseURL = 'http://localhost:3000';
// async function queryDate() {
// var res = await axios.get('/adata');
// // 1. console.log(res.data);
// return res.data;
// };
// // 1. queryDate();
// queryDate().then(res => {
// console.log(res);
// });
// 模拟异步
async function queryDate() {
var res = await new Promise(function(resolve, reject) {
setTimeout(function() {
resolve('nihao');
}, 1000);
})
return res;
};
queryDate().then(date => {
console.log(date);
});
</script>
5.2 async/await 处理多个异步请求
<script type="text/javascript">
axios.defaults.baseURL = "http://localhost:3000";
async function queryDate() {
var info = await axios.get("async1");
var ret = await axios.get("async2?info=" + info.data);
return ret.data;
};
queryDate().then(data => {
console.log(data);
})
</script>
<!-- 接口 -->
// async-await
app.get('/async1', (req, res) => {
res.send('Hello1');
});
app.get('/async2', (req, res) => {
if (req.query.info == 'Hello') {
res.send('Hello Async-Await!');
} else {
res.send('Error');
}
});