目录
一、干了什么?
二、问题及解决方案
2.1 出现问题:axios循环发送请求并没有按顺序执行
2.1.1 错误代码
2.1.2 代码实现逻辑
2.1.3 出错信息
2.2 解决过程分析
2.2.1 错误部分
2.2.2 解决await在forEach不起作用
2.2.3 解决方法内axios通信顺序问题
2.3 效果展示
总结
一、干了什么?
2022/6/3 系统出现了一个bug,在新建实体表时出现了问题。发现新建的表字段数不够。
新建表的字段是从元信息表中获取的。
证明是元信息表还没有创建完成,系统就已经调用这些元信息开始创建实际的表了。
分析分析,发现还是axios异步通信的问题!!!
简单介绍一下错在哪里和怎么解决吧,希望以后开发过程中能够避开~~
二、问题及解决方案
2.1 出现问题:axios循环发送请求并没有按顺序执行
2.1.1 错误代码
click3(){
//这里就直接复制粘贴即可
this.submitForm3();
this.dialogVisible=true
},
submitForm3() {
this.columnList.forEach((item,index) => {
let params = new URLSearchParams()
params.append('DBid',this.dbid)
params.append('CHARTid',this.chartid)
params.append('MEN',this.columnList[index])
params.append('Types',this.aboutColumns.types[index])
params.append('ZDes',this.aboutColumns.ZDescrs[index])
params.append('ZN',this.aboutColumns.ZNames[index])
axios.post(`api/insertMeta`,params).then(res=>{
console.log('表的详细信息第 '+index+' 列已经发出去了')
console.log(res.data)
})
});
//创建实体表
let params1 = new URLSearchParams()
params1.append('DBid',this.dbid)
params1.append('CHARTid',this.chartid)
params1.append('EN',this.biaoF.Ename)
axios.post(`api/createUTable`,params1).then(res=>{
console.log('已发出实体表相关信息')
console.log(res.data)
})
},
2.1.2 代码实现逻辑
1.点击按钮
调用submitForm3()方法
2.submitForm3()方法逻辑:
step1:使用forEach循环使用axios向后端传递新建表meta信息,后端在元信息表中插入该条信息;
step2:step1完成之后,使用axios像后端传递新建表信息,并创建表。
3.创建表的后端逻辑
利用2中step2传过来的dbid,chartid,EN,找到要新建表的元信息表,使用map存储元信息,利用map使用JDBC语句创建表,表名为EN。
2.1.3 出错信息
根据控制台输出
console.log('表的详细信息第 '+index+' 列已经发出去了')
发现发出去的列并不是按顺序的,而是随机的,顺序是3,0,1,2也可能是1,2,3,0。
总之顺序完全随机。
根据后端输出1
//controller层
System.out.println(DBid+"----------------------"+
CHARTid+"----------------------"+MEN+"----------------------");
System.out.println(Types+"----------------------"+
ZDes+"----------------------"+ZN+"----------------------");
int dbid = Integer.parseInt(DBid);
int chartid = Integer.parseInt(CHARTid);
System.out.println("把传过来的dbid转为int:"+dbid+"
把传过来的chartid转为int:"+chartid);
//service层
System.out.println("插入数据到"+metaName+"表中成功与否:"+ insertMeta );
发现后端接受前端meta信息时,也不是顺序执行的,可能在一条meta信息还没有插入到元信息表中,另一条信息就从前端传过来了。
控制台输出完全是混乱的。
根据后端输出2
//controller层
String DBid =req.getParameter("DBid").trim();
String Chartid =req.getParameter("CHARTid").trim();
String CName =req.getParameter("EN").trim();
//首先获取DBid 和 CHARTid
System.out.println(DBid+"----------------------"+Chartid+"
----------------------");
//service层
System.out.println("到这一步");
再加上在传输完meta列表之后,会调用创建实体表方法createUTable()axios异步通信同样导致了可能meta列表传完了,但是后端还没有实现所有meta信息都插入元信息表中时,就调用创建表方法,导致创建表为空(出错)、创建表字段不够 、创建表字段顺序不对等问题。
2.2 解决过程分析
2.2.1 错误部分
已经发现是axios异步通信的错误,只要让代码按照逻辑顺序执行就好了。
所以刚开始就想要直接使用async/await直接使用。这个怎么用之前讲过。有需要可以看看axios通信导致vue前端数据不一致。
修改后代码如下:
async click3(){
//这里就直接复制粘贴即可
await this.submitForm3();
this.dialogVisible=true
},
async submitForm3() {
this.columnList.forEach((item,index) => {
let params = new URLSearchParams()
params.append('DBid',this.dbid)
params.append('CHARTid',this.chartid)
params.append('MEN',this.columnList[index])
params.append('Types',this.aboutColumns.types[index])
params.append('ZDes',this.aboutColumns.ZDescrs[index])
params.append('ZN',this.aboutColumns.ZNames[index])
await axios.post(`api/insertMeta`,params).then(res=>{
console.log('表的详细信息第 '+index+' 列已经发出去了')
console.log(res.data)
})
});
//创建实体表
let params1 = new URLSearchParams()
params1.append('DBid',this.dbid)
params1.append('CHARTid',this.chartid)
params1.append('EN',this.biaoF.Ename)
await axios.post(`api/createUTable`,params1).then(res=>{
console.log('已发出实体表相关信息')
console.log(res.data)
})
},
结果发现报错:
await is a reserved word
怎么回事呢?——原来是await在forEach不起作用!
具体分析,请移步如何在 JS 循环中正确使用 async 与 await
2.2.2 解决await在forEach不起作用
await在forEach循环中不起作用,将forEach改为for循环即可
改前:
this.columnList.forEach((item,index) => {
let params = new URLSearchParams()
params.append('DBid',this.dbid)
params.append('CHARTid',this.chartid)
params.append('MEN',this.columnList[index])
params.append('Types',this.aboutColumns.types[index])
params.append('ZDes',this.aboutColumns.ZDescrs[index])
params.append('ZN',this.aboutColumns.ZNames[index])
await axios.post(`api/insertMeta`,params).then(res=>{
console.log('表的详细信息第 '+index+' 列已经发出去了')
console.log(res.data)
})
});
改后:
for(let index = 0;index < this.columnList.length;index++){
let params = new URLSearchParams()
params.append('DBid',this.dbid)
params.append('CHARTid',this.chartid)
params.append('MEN',this.columnList[index])
params.append('Types',this.aboutColumns.types[index])
params.append('ZDes',this.aboutColumns.ZDescrs[index])
params.append('ZN',this.aboutColumns.ZNames[index])
console.log("MEN:"+this.columnList[index]+"__"+"Types:"
+this.aboutColumns.types[index]
+"__"+"ZDes:"+this.aboutColumns.ZDescrs[index]+"__"+"ZN:"
+this.aboutColumns.ZNames[index]);
await axios.post(`api/insertMeta`,params).then(res=>{
console.log(params)
console.log('表的详细信息第 '+index+' 列已经发出去了')
console.log(res.data)
})
}
这样就解决了前端发送执行的问题,但是在进行发送完成之后,会调用createUTable()方法,同样也是利用axios异步通信。这样仍然可能导致在最后一个meta信息还没有插入元信息表时,就已经创建了实体表。
2.2.3 解决方法内axios通信顺序问题
因为要等所有的meta信息插入元信息表,再创建实体表。所以这里:
step1:直接在click3中,创建两个新方法:
方法一submitForm3():把所有的meta信息插入元信息表。
方法二createUTable():创建实体表。
step2:使用async/await,使这两个方法顺序执行
就可以解决啦!
具体实现代码如下:
async click3(){
//这里就直接复制粘贴即可
await this.submitForm3();
//创建实体表
await this.createUTable();
this.dialogVisible=true
},
async submitForm3() {
for(let index = 0;index < this.columnList.length;index++){
await this.insertMeta(index);
}
},
async insertMeta(index){
let params = new URLSearchParams()
params.append('DBid',this.dbid)
params.append('CHARTid',this.chartid)
params.append('MEN',this.columnList[index])
params.append('Types',this.aboutColumns.types[index])
params.append('ZDes',this.aboutColumns.ZDescrs[index])
params.append('ZN',this.aboutColumns.ZNames[index])
console.log("MEN:"+this.columnList[index]+"__"+"Types:"
+this.aboutColumns.types[index]+"__"+"ZDes:"
+this.aboutColumns.ZDescrs[index]+"__"+"ZN:"
+this.aboutColumns.ZNames[index]);
await axios.post(`api/insertMeta`,params).then(res=>{
console.log(params)
console.log('表的详细信息第 '+index+' 列已经发出去了')
console.log(res.data)
})
},
async createUTable(){
let params1 = new URLSearchParams()
params1.append('DBid',this.dbid)
params1.append('CHARTid',this.chartid)
params1.append('EN',this.biaoF.Ename)
await axios.post(`api/createUTable`,params1).then(res=>{
console.log('已发出实体表相关信息')
console.log(res.data)
})
},
这样就简单明了很多,也方便找错误。
2.3 效果展示
前端顺序发送:
后端顺序执行:
数据库中创建的表:
元信息表:
实体表:
总结
主要还是axios通信的问题,以及实现顺序执行时使用async/await的一些限制。