前端异步调用无法保证先后顺序的处理方式

作者 Billy 日期 2025-04-08
前端异步调用无法保证先后顺序的处理方式

问题描述

  1. vuejs2 nodejs14
  2. 问题页面加载时,created()中调用数据的初始化加载函数,初始化函数是异步的
  3. 父页面调用问题页面时,直接调用handleSearch(val)函数,函数内异步调用后端接口进行查询操作,后端接口返回数据时,会根据初始化的数据进行页面渲染
  4. 当#3步骤中的数据查询接口返回响应时,无法保证#2中的初始化函数已经执行完毕,所以页面渲染时,会因为初始化函数未执行完毕而报错
  5. 从浏览器控制台上观察到的结果,一旦初始化函数执行时间高于查询接口的调用时间,就会报错
  6. 除了以上步骤简化的描述以外,还包含了多个异步调用的步骤,由于与问题无关,没有详细描述,但正是这些异步调用,导致重构成本大大提升

解决方案

  1. 统一入口,由于进入该页面的入口只有一个,因此将初始化函数放入handleSearch()函数中的头部位置
  2. 将初始化函数用async标记,调用时使用await标记
  3. 使用Promise构造函数,将初始化函数重构:
// 初始化函数
async init() {
return new Promise(async (resolve, reject) =>{
if(Object.keys(this.allOptions).length === 0) {
// 主要、导致问题的初始化逻辑
const res = await getSpotList();
if (res.code == 200) {
this.allOptions = res.data;
this.zbtbName = res.data.matterFirst[0].name;
this.zbtbFor = res.data.matterSecond.map(t => {
return {
code: t.code,
name: t.name,
count: 0,
};
});
resolve(this.allOptions);
this.handleFilterMain(); // 其他无关紧要的初始化逻辑
}
}
})

}
  1. Promise 构造函数接受一个函数作为参数,该函数是同步的并且会被立即执行,所以我们称之为起始函数。起始函数包含两个参数 resolve 和 reject,分别表示 Promise 成功和失败的状态。
  2. 在本例中,this.allOptions是导致问题出现的值,因此在它初始化完成后,执行resolve(this.allOptions),表示异步函数已执行成功,后续逻辑this.handleFilterMain()继续异步执行

问题分析

  1. 本项目是一个提交时间跨度极大,人员跨度极大的老旧项目,由于一些原因,一直处于维护中的状态,会出现很多类似的找不到原因和首要提交人的代码,相信很多人也会遇到类似问题
  2. 我们能做的,只能是找寻问题根因,然后从尽量不影响原有逻辑的情况下,进行修改,一般来讲,重构会引发更多的问题..

参考链接

  1. Promise