项目场景:
提示:这里是基于vue的async/await异步请求加请求中携带返回值失效的问题
情景描述:这里的情况是在一个方法中,
通过 if 和 else 分别调用不同的请求,并且请求里面同时包含了其他请求,且携带条件返回值的情况。
所以小伙伴可以先查看看自己是否对应,快速排错,不过也可以先收藏,我相信你们迟早会用到,嘿嘿
问题描述
提示:废话不多说,请看VCR,为了方便理解只保留主要代码
在进行第一个接口调用后,我需要再进行第二个接口调用并获取返回值,在这里我们可以看到打印的执行顺序其实是没有问题的,4号位获取数据后,打印值还存在,但是5号返回值却没了?
以下是主体代码,即调用数据返回的一方。
async addAssociation(infos, sIndex, wIndex) {
// 含有数据进行组件数据注入
if (infos.additionalInfoes != null && infos.additionalInfoes.length > 0) {
console.log("有数据-infos", infos);
let AssInfo = infos.additionalInfoes;
//为方便观看,省略部分变量...
AssInfo.forEach((item) => {
if (item.questionType == 1) {
//为方便观看,省略...
} else {
console.log(1);
this.getAssFinfo(item.refId).then((infos) => {
console.log("5-infos",infos);
let abbreviation = this.parameterProcess(infos.subject, 25);
//以下内容已省略
});
}
});
} else {
await gettranslist(infos.word).then((res) => {
if (res.code == 200) {
let data = res.data;
}
});
}
},
接下来展示被调用返回值的方法
async getAssFinfo(id) {
console.log(2);
await getfillquestiondetailApi({
id: id,
}).then((res) => {
console.log(3);
if (res.code == 200) {
console.log(4,res.data);
return res.data;
}
});
},
原因分析:
注意:关于await等待异步返回值的易错点
可能眼尖的小伙伴已经发现问题了,既然调用方法,4节点返回值是正常的,但是5节点不仅没有数据还多了一个报错 TypeError: Cannot read properties of undefined (reading ‘subject’)
很明显,这个报错就是提示你数据未定义,那问题只能出在返回上
这个地方,最好添加打印顺序1、2、3、4、5,来帮你确定是否是报错的值提前被使用了,导致的值报错未定义,而且因为执行顺序也没问题也让我们更直观了解到报错就出在回调方法上。
那咱们继续分析这个回调
在这里,getAssFinfor方法,咱们使用了async /await让其变成了一个异步函数,await关键字等待getfillquestiondetailApi方法的返回的Promise 结果,且按照正常顺序,.then()方法也获取到了返回结果res,本来到这里都挺正常的。
但是问题就出在这个**.then()里面进行的返回值**;
-
返回的 Promise 在解析后,内部的 res.data 是通过 .then() 方法处理的,而 return res.data; 并不会直接返回给 getAssFinfo 的调用者,也就是最大的那个方法,而是作为 .then() 的回调函数的返回值。
-
由于 getAssFinfo 没有显式返回任何内容,其实际返回值是 undefined,因此在 addAssociation 方法中使用 await this.getAssFinfo(item.refId) 时,得到的是 undefined。
总结一下:这个return,它只会返回给 .then() 而不是整个 getAssFinfo 函数。
这意味着,getAssFinfo 函数本身并不会返回任何值,因为 await 关键字后面的 Promise 没有被等待。实际上,getAssFinfo 函数只会立即返回一个未完成的 Promise。
如果,这么说大家有点懵,可以直接看解决方法或者看我的图就能懂这个异步请求的大概原理了。
知识点补充:
注意:小板凳做好,我们要长脑子了,不爱学的小鬼请直接跳到解决方案
我们先来理解一下返回函数的概念吧
所以在图中,你大概能够理解咱们整个方法的程序的运作方式了。
首先,addAssociation方法中,我们先直接调用了getAssFinfo()方法;
然后,getAssFinfo内部明确了await等待getfillquestiondetailApi()请求异步执行完毕;
再然后,因为getfillquestiondetailApi()返回的 Promise 在解析后,使用了.then()的回调方法处理;
其次,咱们直接在.then()中就执行了return的操作,中断了该方法的执行,他也只会返回给.then()而不是整个getAssFinfo(),这也是没有返回值的原因;
再其次,在执行完成的子方法中执行返回;
最后,父方法获得返回值继续
当然,在这里我的比喻可能有些许不恰当,若存在错误的地方,还请大神斧正,谢谢。
总结:.then()中返回的值无法传递到整个方法中,可以提前定义传递
解决问题:
把返回值的操作放到整个方法中而不是回调处理中
在这里,可以提前定义一个obj对象,而.then()中处理的值直接赋值给obj,并最终在方法的最后部分返回整个参数
async getAssFinfo(id) {
let obj = {};
await getfillquestiondetailApi({
id: id,
}).then((res) => {
if (res.code == 200) {
console.log(4,res.data);
obj = res.data;
}
});
return obj;
},
总结问题
其实到这里,一直以来都是一个很小的问题,说白了就是基本功不扎实,所以写到这里我也是希望能够帮助到和我一样的小伙伴,不用每次都躲过去,直接理解并解决底层问题,少爬一些坑。
如果喜欢我的博客,别忘了给我一键三连哦,观众老爷~~
瑞思拜~