Vue中for循环调用异步GET请求仅最后一次生效问题排查
问题分析
你遇到的核心问题是异步操作执行时机与变量作用域冲突:
- 同步for循环会快速遍历所有元素,每次循环直接修改全局的
val_ia,循环结束时val_ia已经是最后一个索引值。 fetch是异步操作,所有请求的回调逻辑(then内代码)会在同步代码执行完毕后才触发,此时val_ia已固定为最后一个值,导致所有数据更新都指向数组最后一个对象。- 控制台先输出所有
val_ia再输出datasend,是因为console.log('val_ia is ' + this.val_ia)是同步执行,而then里的console.log("datasend")是异步逻辑,会排在所有同步代码之后执行。
解决方案
方案1:将索引作为参数传入异步函数
把循环索引i直接传给getAllData,让每个异步请求持有独立的索引值,避免被全局变量覆盖:
getDatafor(){ for(let i = 0; i < this.desserts.length; i++){ this.getAllData(i); // 传入当前循环索引 } }, async getAllData(index) { // 接收索引参数 console.log('val_ia is ' + index) const tag_id_name = encodeURIComponent(this.tag_id[index]); const url = this.$api.getRESTApiUri() + `/all/last_id/${tag_id_name}`; return fetch(url) .then(res => res.text()) .then((result) => { const data = JSON.parse(result); console.log("datasend") this.desserts[index].tension = data[0].adc_v/100 this.desserts[index].courant = data[0].adc_i; this.desserts[index].temperature = data[0].temperature/100; }) .catch((error) => { console.log(error) }); },
方案2:用async/await实现顺序请求
如果需要严格按顺序执行请求(控制台输出完全符合你的预期),可以用for...of循环配合await:
async getDatafor(){ // 标记为异步函数 for(let i = 0; i < this.desserts.length; i++){ console.log('val_ia is ' + i) await this.getAllData(i); // 等待当前请求完成再进入下一次循环 } }, async getAllData(index) { const tag_id_name = encodeURIComponent(this.tag_id[index]); const url = this.$api.getRESTApiUri() + `/all/last_id/${tag_id_name}`; try { const res = await fetch(url); const result = await res.text(); const data = JSON.parse(result); console.log("datasend") this.desserts[index].tension = data[0].adc_v/100 this.desserts[index].courant = data[0].adc_i; this.desserts[index].temperature = data[0].temperature/100; } catch(error) { console.log(error) } },
这个方案会让请求按顺序执行,控制台输出严格遵循val_ia is 0→datasend→val_ia is 1→datasend的顺序。
额外修正点
你的data选项里定义的是dessert:[],但代码中使用的是desserts,注意修正拼写错误。
内容的提问来源于stack exchange,提问作者Guts
相关产品推荐
相关产品推荐

