一、基础复习
1.前后端交互
通过浏览器调用接口,拿到后台的数据,再做前端的数据渲染。
2. 接口调用方式
因为Vue不操作DOM,所以用后两种
- ajax
- jQuery的ajax
- fetch
- axios
3. URL
3.1 传统的URL
3.2 Restful格式的URL
4. promise
ES6引入的一种语法,专门用来处理异步编程。
JS层面的异步编程有:
- 定时任务
- ajax
- 事件函数
4.1 演示jQuery的ajax的异步
先执行外面的,后执行里面的
路由
app.get('/data', (req, res) => {
res.send('Hello World!')
})
前端
var ret = '---';
$.ajax({
url: 'http://localhost:3000/data',
success: function(data) {
ret = data;
console.log(ret) // 2 Hello World!
}
});
console.log(ret) // 1 ---
控制台先打印 --- 后打印 Hello World!
多次写ajax请求,顺序无法控制
路由
app.get('/data', (req, res) => {
res.send('Hello World!')
})
app.get('/data1', (req, res) => {
setTimeout(function(){
res.send('Hello TOM!')
},1000);
})
app.get('/data2', (req, res) => {
res.send('Hello JERRY!')
})
前端
$.ajax({
url: 'http://localhost:3000/data',
success: function(data) {
console.log(data)
}
});
$.ajax({
url: 'http://localhost:3000/data1',
success: function(data) {
console.log(data)
}
});
$.ajax({
url: 'http://localhost:3000/data2',
success: function(data) {
console.log(data)
}
});
级别相同,没有顺序
若想要按顺序打印,需要嵌套(回调地狱)
$.ajax({
url: 'http://localhost:3000/data',
success: function(data) {
console.log(data)
$.ajax({
url: 'http://localhost:3000/data1',
success: function(data) {
console.log(data)
$.ajax({
url: 'http://localhost:3000/data2',
success: function(data) {
console.log(data)
}
});
}
});
}
});
4.2 promise演示
- 解决回调地狱问题
- 简洁的API,更容易控制异步操作
简单演示
var p = new Promise(function(resolve, reject){
// 这里用于实现异步任务
setTimeout(function(){
var flag = false;
if(flag) {
resolve('hello');
}else{
reject('出错了');
}
}, 100);
});
p.then(function(data){
console.log(data) // flag为true打印hello
},function(info){
console.log(info) // flag改为false打印 出错了
});
成功时触发resolve,失败触发reject
基于promise处理ajax请求
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)
return queryData('http://localhost:3000/data1');
})
.then(function(data){
console.log(data);
return queryData('http://localhost:3000/data2');
})
.then(function(data){
console.log(data)
});
路由:
app.get('/data', (req, res) => {
res.send('Hello World!')
})
app.get('/data1', (req, res) => {
setTimeout(function(){
res.send('Hello TOM!')
},1000);
})
app.get('/data2', (req, res) => {
res.send('Hello JERRY!')
})
显示:
then参数中函数的返回值
- 返回promise对象,该对象会调用下一个then
queryData('http://localhost:3000/data')
.then(function(data){
return new Promise(function(resolve, reject){
setTimeout(function(){
resolve(123);
},1000)
});
})
.then(function(data){
console.log(data); // 123
})
- 返回普通值,直接传递给下一个then
queryData('http://localhost:3000/data')
.then(function(data){
return 'hello';
})
.then(function(data){
console.log(data) // hello
})
promise常用的API
- .then() 获取异步的正确结果
- .catch() 获取异常信息
- .finally() 成功与否都会执行
function foo() {
return new Promise(function(resolve, reject){
setTimeout(function(){
// resolve(123);
reject('error');
}, 100);
})
}
foo()
.then(function(data){
console.log(data) // 123 接收resolve
})
.catch(function(data){
console.log(data) // error 接收error
})
.finally(function(){
console.log('finished') // finished
});
- Promise.all() 并发处理多个异步函数,所有任务执行完才能得到结果
- Promise.race() 并发处理多个异步函数,只要一个函数执行完就得到结果
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)
})
路由
app.get('/a1', (req, res) => {
setTimeout(function(){
res.send('Hello TOM!')
},1000);
})
app.get('/a2', (req, res) => {
setTimeout(function(){
res.send('Hello JERRY!')
},2000);
})
app.get('/a3', (req, res) => {
setTimeout(function(){
res.send('Hello SPIKE!')
},3000);
})
5. fetch
fetch是原生JS,且会返回Promise
fetch(url, options).then()options默认get时可省略
5.1 fetch的基本使用
- text() 方法属于fetchAPI的一部分,它返回一个Promise实例对象,用于获取后台返回的数据
<script type="text/javascript">
fetch('http://localhost:3000/fdata').then(function(data){
return data.text();
}).then(function(data){
console.log(data);
})
</script>
路由
app.get('/fdata', (req, res) => {
res.send('Hello Fetch!')
})
显示:控制台打印 Hello Fetch!
5.2 fetch的请求参数
get delete
fetch('http://localhost:3000/books?id=123', {
method: 'get'
})
.then(function(data){
return data.text();
}).then(function(data){
console.log(data)
});
fetch('http://localhost:3000/books/456', {
method: 'get'
})
.then(function(data){
return data.text();
}).then(function(data){
console.log(data)
});
fetch('http://localhost:3000/books/789', {
method: 'delete'
})
.then(function(data){
return data.text();
}).then(function(data){
console.log(data)
});
路由
app.get('/books', (req, res) => {
res.send('传统的URL传递参数!' + req.query.id)
})
app.get('/books/:id', (req, res) => {
res.send('Restful形式的GET请求传递参:查询' + req.params.id)
})
app.delete('/books/:id', (req, res) => {
res.send('Restful形式的DELETE请求传递参数:删除' + req.params.id)
})
控制台打印:
- 传统的URL传递参数!123
- Restful形式的GET请求传递参:查询456
- Restful形式的DELETE请求传递参数:删除789
post put
fetch('http://localhost:3000/books', {
method: 'post',
body: 'uname=lisi&pwd=123',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
})
.then(function(data){
return data.text();
}).then(function(data){
console.log(data)
});
fetch('http://localhost:3000/books', {
method: 'post',
body: JSON.stringify({
uname: '张三',
pwd: '456'
}),
headers: {
'Content-Type': 'application/json'
}
})
.then(function(data){
return data.text();
}).then(function(data){
console.log(data)
});
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)
});
路由
app.post('/books', (req, res) => {
res.send('POST请求传递参数xwf:添加' + req.body.uname + '---' + req.body.pwd)
})
app.post('/books', (req, res) => {
res.send('POST请求传递参数json:添加' + req.body.uname + '---' + req.body.pwd)
})
app.put('/books/:id', (req, res) => {
res.send('PUT请求传递参数:修改' + req.params.id + '---' + req.body.uname + '---' + req.body.pwd)
})
控制台打印:
- POST请求传递参数xwf:添加lisi---123
- POST请求传递参数json:添加张三---456
- PUT请求传递参数:修改123---张三---789
5.3 fetch响应结果
text() 响应数据为json字符串格式
fetch('http://localhost:3000/json').then(function(data){
return data.text();
}).then(function(data){
var obj = JSON.parse(data);
console.log(obj.uname,obj.age,obj.gender)
})
json() 响应数据为json对象格式
fetch('http://localhost:3000/json').then(function(data){
return data.json();
}).then(function(data){
console.log(data)
console.log(data.uname)
})
6. axios
网址:https://github.com/axios/axios
6.1 axios的基本使用
- ret自定义
- data固定,用于获取后台的真实数据
<script type="text/javascript" src="js/axios.js"></script>
<script type="text/javascript">
axios.get('http://localhost:3000/adata').then(function(ret){
console.log(ret.data)
})
</script>
路由
app.get('/adata', (req, res) => {
res.send('Hello axios!')
})
控制台打印出 Hello axios!
6.2 axios的请求参数
get请求参数(查询)
axios.get('http://localhost:3000/axios?id=123').then(function(ret){
console.log(ret.data) // axios get 传递参数123
})
axios.get('http://localhost:3000/axios/123').then(function(ret){
console.log(ret.data) // axios get (Restful) 传递参数123
})
axios.get('http://localhost:3000/axios', {
params: {
id: 789
}
}).then(function(ret){
console.log(ret.data) // axios get 传递参数789
})
对应路由
app.get('/axios', (req, res) => {
res.send('axios get 传递参数' + req.query.id)
})
app.get('/axios/:id', (req, res) => {
res.send('axios get (Restful) 传递参数' + req.params.id)
})
app.get('/axios', (req, res) => {
res.send('axios get 传递参数' + req.query.id)
})
delete请求参数(删除)
同上,get换delete
post请求参数(添加)
// 请求参数为 json字符串 类型
axios.post('http://localhost:3000/axios', {
uname: 'lisi',
pwd: 123
}).then(function(ret){
console.log(ret.data)
})
// x-w-f-u字符串 =& 类型
var params = new URLSearchParams();
params.append('uname', 'zhangsan');
params.append('pwd', '111');
axios.post('http://localhost:3000/axios', params).then(function(ret){
console.log(ret.data)
})
路由
app.post('/axios', (req, res) => {
res.send('axios post 传递参数' + req.body.uname + '---' + req.body.pwd)
})
put请求参数(修改)
axios.put('http://localhost:3000/axios/123', {
uname: 'lisi',
pwd: 123
}).then(function(ret){
console.log(ret.data)
})
路由
app.put('/axios/:id', (req, res) => {
res.send('axios put 传递参数' + req.params.id + '---' + req.body.uname + '---' + req.body.pwd)
})
6.3 axios的响应结果
响应结果的主要属性
- data:响应数据
- headers:响应头信息
- status:响应状态码
- statusText:响应状态信息
axios.get('http://localhost:3000/axios-json').then(function(ret){
console.log(ret);
console.log(ret.data.uname); // lisi
})
路由
app.get('/axios-json', (req, res) => {
res.json({
uname: 'lisi',
age: 12
});
})
axios全局设置
// 超过3秒没响应,返回服务器出错
axios.defaults.timeout = 3000;
// 配置请求的基准URL地址,后面请求会拼接
axios.defaults.baseURL = 'http://localhost:3000/';
// 配置请求头信息
axios.defaults.headers['mytoken'] = 'hello';
axios.get('axios-json').then(function(ret){
console.log(ret.data.uname)
})
6.4 axios拦截器
请求拦截器
config是请求对象,一定要写return。
axios.interceptors.request.use(function(config) {
console.log(config.url);
config.headers.mytoken = 'nihao';
return config;
}, function(err){
console.log(err)
})
响应拦截器
res是响应对象
axios.interceptors.response.use(function(res) {
var data = res.data;
return data;
}, function(err){
console.log(err)
})
7. async/await
ES7引入的语法,更加方便的进行异步操作
处理单个异步请求
- async作为一个关键字放到函数前面,函数就会隐式返回一个promise
- await 关键字只能在使用 async 定义的函数中使用不能单独使用,后面可以直接跟一个 Promise实例对象
async function queryData() {
var ret = await new Promise(function(resolve, reject){
setTimeout(function(){
resolve('nihao')
},1000);
})
return ret;
}
// 可以使用then 进行链式编程
queryData().then(function(data){
console.log(data) // nihao
})
处理多个异步请求
axios.defaults.baseURL = 'http://localhost:3000';
async function queryData() {
var info = await axios.get('async1');
var ret = await axios.get('async2?info=' + info.data); //
return ret.data;
}
queryData().then(function(data){
console.log(data) // world
})
路由
app.get('/async1', (req, res) => {
res.send('hello')
})
app.get('/async2', (req, res) => {
if(req.query.info == 'hello') {
res.send('world')
}else{
res.send('error')
}
})
控制台打印 world