异步效果分析
多次异步调用的依赖分析
Promise是异步编程的一种解决方案,从语法上讲,Promise是一个对象,从它可以获取异步操作的消息(解决回调地狱)
使用Promise主要的好处
<script type="text/javascript">
/**
* Promise基本使用
*/
var p = new Promise(function(resolve,reject){
//这里用于实现异步任务(Ajax)
setTimeout(function(){
var flag = false;
if(flag){
//正常情况
resolve('hello');
}else{
//异常情况
reject('error');
}
},100)
});
p.then(function(data){
console.log(data);
},function(info){
console.log(info)
});
</script>
返回的该实例对象会调用下一个then
返回的普通值会直接传递给下一个then,通过then参数中函数的参数接受该值
<script type="text/javascript">
/*
then参数中的函数返回值
*/
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){
return queryData('http://localhost:3000/data1');
})
.then(function(data){
return new Promise(function(resolve, reject){
setTimeout(function(){
//resolve(123);
reject("error");
},1000)
});
})
.then(function(data){
return 'hello';
})
.then(function(data){
console.log(data)
})
</script>
实例方法
<script type="text/javascript">
/**
* Promise常用API-实例方法
*/
function foo(){
return new Promise(function(resolve,reject){
//定义一个异步定时任务
setTimeout(function(){
resolve(123);
},1000);
})
}
foo() //正常
.then(function(data){
console.log(data)
}) //错误
.catch(function(data){
console.log(data)
}) //结束
.finally(function(){
console.log("finished")
});
# 这种写法也是ok的
foo()
.then(function(data){
console.log(data)
},function(data){
console.log(data)
})
.finally(function(){
console.log("finished")
})
</script>
对象方法
注意:这里的result是一个数组,里面的数据跟p1,p2,p3中传递过来的一一对应
<script type="text/javascript">
/**
* Promise常用API-对象方法
*/
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:8080/a1');
var p2 = queryData('http://localhost:8080/a2');
var p3 = queryData('http://localhost:8080/a3');
//并发执行(全部执行完才执行)
Promise.all([p1,p2,p3]).then(function(result){
console.log(result)
})
//(zhiyao)
Promise.race([p1,p2,p3]).then(function(result){
console.log(result)
})
</script>
更简单的数据获取方式,功能更前大、更灵活,可以看做是xhr的升级版,他还是基于Promise实现的
语法结构
实例
<script type="text/javascript">
/**
* Fetch API基本用法
*/
fetch('http://112.74.167.52:8089/channel/createOrder').then(function(data){
//这里的text()方法属于fetch API一部分,它返回一个Promise对象,用于获取后台返回的数据
return data.text();
}).then(function(data){
console.log(data)
})
</script>
常用配置选项
method(String) ,http请求方式:GET、POST、PUT、DELETE,默认是GET
body(String) ,请求体
headers(Object) ,请求头的设置
GET方法传递参数
POST方法传参
正常开发中,使用application/json格式居多
实例
<script type="text/javascript">
/**
* Fetch 请求参数
*/
fetch('http://112.74.167.52:8089/channel/createOrder',{
method:'post',
body:JSON.stringify({
'orderCode':'AS202012010001CN'
}),
headers:{
'Content-Type':'application/json'
}
})
.then(data => {
return data.text();
})
.then(data =>{
console.log(data);
})
</script>
响应数据格式
<script type="text/javascript">
/**
* Fetch 请求参数
*/
fetch('http://112.74.167.52:8089/channel/createOrder',{
method:'post',
body:JSON.stringify({
'orderCode':'AS202012010001CN'
}),
headers:{
'Content-Type':'application/json'
}
})
.then(data => {
//将数据转为json格式
//return data.text();
return data.json();
})
.then(ret =>{
//var json = JONS.parse(ret);
//console.log(json.msg)
//这样就可以取出具体的值
console.log(ret.msg);
console.log(ret.resCode);
console.log(ret.obj);
})
</script>
axios是一个基于Promise用于浏览器和node.js的和HTTP客户端
简单示例
<html>
<head>
<meta charset="utf-8" />
<title>title>
<script src="js/axios.js" type="text/javascript" charset="utf-8">script>
head>
<body>
<script type="text/javascript">
/**
* axios的基本使用
* 发送get请求
*/
axios.get('http://112.74.167.52:8089/channel/get').then(ret => {
//这里的data是axios的固定属性,用于获取后台返回的实际数据
console.log(ret.data);
})
script>
body>
html>
get传递参数
//拼接的方式
axios.get('http://112.74.167.52:8089/channel/get?id=1').then(ret => {
//这里的data是axios的固定属性,用于获取后台返回的实际数据
console.log(ret.data);
})
//restful形式的请求
axios.get('http://112.74.167.52:8089/channel/get/1').then(ret => {
//这里的data是axios的固定属性,用于获取后台返回的实际数据
console.log(ret.data);
})
// 带对象的参数:params
axios.get('http://112.74.167.52:8089/channel/get',{
params:{
id:123,
name:'pihao'
}
}).then(ret => {
console.log(ret.data);
})
post请求传递参数
post请求,传递json格式的数据
/**
* axios
* post请求,请求体为对象 json格式的数据
*/
axios.post('http://112.74.167.52:8089/channel/createOrder',{
orderCode:'AS202012030001CN'
}).then(ret => {
console.log(ret.data);
})
post请求,表单格式的数据
响应的主要属性
实例
//url
axios.defaults.baseURL='http://112.74.167.52:8089/channel/';
//timeout
axios.defaults.timeout=3000;
//headers
axios.defaults.headers['mytoken']='hello';
axios.post('createOrder',{
orderCode:'AS202012030001CN'
}).then(ret => {
console.log(ret.data);
})
请求拦截器
拦截器实例
<script type="text/javascript">
/**
* axios请求拦截器
*/
axios.interceptors.request.use(function(config){
//配置请求头
config.headers.mytoken = 'pihao';
//请求的其他配置。。。
//还可以通过config.url获取请求地址,然后对请求地址做相应配置
return config;
},function(err){
console.log(err);
})
//测试请求
axios.get('http://112.74.167.52:8089/channel/get').then(ret=>{
console.log(ret.data);
});
</script>
响应拦截器
拦截器实例
/**
* axios响应拦截器
*/
axios.interceptors.response.use(function(res){
//这里的res就是那个还没处理的响应数据
//这里做一个小小的处理
var data = res.data;
//直接返回json数据
return data;
},function(err){
console.log(err);
})
//测试请求
axios.get('http://112.74.167.52:8089/channel/get').then(ret=>{
//注意:这里没有 .data
console.log(ret);
});
语法
实例
<script type="text/javascript">
/**
* async/await 处理异步操作
*/
axios.defaults.baseURL='http://112.74.167.52:8089/channel/'
//async处理异步任务,返回的其实一个Promise对象,这个对象里面的传的参数的响应的结果
async function queryData(){
var res = await axios.get('get');
return res.data;
}
//通过then处理Promise
queryData().then(data => {
console.log(data); //已经处理过了的json响应数据
})
</script>
什么?上个例子懵逼?,那么看看下面这个简历的例子
<script type="text/javascript">
/**
* async/await 处理异步操作
*/
async function queryData(){
var res = await new Promise(function(resolve,reject){
setInterval(function(){
resolve('async test');
},2000);
})
return res;
}
//通过then处理Promise
queryData().then(data => {
console.log(data); //拿到处理的结果 async test
})
</script>
第一个请求的结果传递给第二个请求的参数
实例
<script type="text/javascript">
/**
* async、await处理多个异步任务
*/
axios.defaults.baseURL = 'http://112.74.167.52:8089/channel/';
async function queryData(){
var info = await axios.get('get');
//将上个请求的返回值作为参数传递给第二个请求
var res = await axios.post('createOrder',info.data);
return res.data;
};
queryData().then(res =>{
console.log(res);
})
</script>
自己用springboot写的java后台,配合前端vue使用
<html>
<head>
<meta charset="utf-8" />
<title>title>
<script src="js/vue.js" type="text/javascript" charset="utf-8">script>
<script src="js/axios.js" type="text/javascript" charset="utf-8">script>
<style type="text/css">
.grid{
margin: auto;
width: 500px;
text-align: center;
}
.grid table{
width: 100%;
border-collapse: collapse;
}
.grid th,td{
padding: 10;
border: 1px dashed orange;
height: 35px;
line-height: 35px;
}
.grid th{
background-color: orange;
}
.grid .book{
padding-bottom: 10px;
padding-top: 5px;
background-color: #F3DCAB;
}
.grid .total{
height: 30px;
line-height: 30px;
background-color: hotpink;
}
style>
head>
<body>
<div id="app">
<div class="grid">
<div>
<h1>图书管理h1>
<div class="book">
<div>
<label for="id">
编号:
label>
<input type="text" id="id" v-model="id" style="width: 30%" :disabled="flag" v-focus/>
<label for="name">
名称:
label>
<input type="text" id="name" v-model="name" style="width: 30%"/>
<button type="button" @click="handel" :disabled="btnFlag">提交button>
div>
div>
div>
<div class="total">
<span>总数:{
{sum}}span>
div>
<table >
<thead>
<tr>
<th>编号th>
<th>名称th>
<th>时间th>
<th>操作th>
tr>
thead>
<tbody>
<tr :key='item.id' v-for='item in books'>
<td>{
{item.id}}td>
<td>{
{item.name}}td>
<td>{
{item.date}}td>
<td>
<a href="#" @click.prevent="toEdit(item.id)">修改a>
<span>|span>
<a href="#" @click.prevent="deleteBook(item.id)">删除a>
td>
tr>
tbody>
table>
div>
div>
<script type="text/javascript">
//设置axios的基准路径
axios.defaults.baseURL='http://112.74.167.52:8089/';
axios.interceptors.response.use(function(res){
return res.data;
},function(error){
console.log(error);
})
var vm = new Vue({
el: '#app',
data:{
id:'',
name:'',
flag:false,
btnFlag:false,
books:[]
},
computed:{
sum:function(){
//计算图书的总数
return this.books.length;
}
},
methods:{
handel: async function(){
//该方法其实可以与编辑图书重用
if(this.flag){
//编辑图书
var res = await axios.put('/books/'+this.id,{
name : this.name
});
if(res == 'success'){
//重新加载列表
this.queryData();
}
this.flag = false;
}else{
//添加图书
entity = {
name:this.name,
id:this.id
};
var result = await axios.post('books',entity);
if(result == 'success'){
this.queryData();
}
}
this.id = '';
this.name = '';
},
toEdit: async function(id){
//编辑的时候禁止修改id
this.flag = true;
//根据id找到相应的数据
var book = await axios.get('/books/'+id);
//找到数据之后填充到页面上
this.id = book.id;
this.name = book.name;
},
deleteBook: async function(id){
//删除图书
var res = await axios.delete('/books/'+id);
if(res == 'success'){
//重新加载数据
this.queryData();
}
},
//加载图书列表
queryData:async function(){
this.books = await axios.get('books');
}
},
filters:{
format:function(val,pattern){
if(pattern == 'yyyy-MM-dd'){
return val.getFullYear()+"-"+(val.getMonth()+1)+"-"+val.getDate();
}
}
},
directives:{
focus:{
inserted:function(el){
el.focus()
}
}
},
watch:{
name:async function(val){
//验证图书名称是否已经存在
var result = await axios.get('/books/book?name='+this.name);
// console.log(result); //true or false
if(result){
//图书名称已经存在
this.btnFlag = true;
}else{
this.btnFlag = false;
}
}
},
mounted:function(){
//该生命周期钩子函数被触发的时候,模板已经可以使用了
//一般此时用于调用接口获取后台数据,然后把数据填充到模板
// axios.get('books').then(res => {
// this.books = res.data;
// })
//上面的方法不够简洁,我们可以在方法中封装函数queryData()
this.queryData();
}
});
script>
body>
html>