异步函数处理数组元素无法返回值的问题排查
我有一个私有异步函数_getAssignment,用于获取单个id对应的数据;还有一个公共函数getAssignments,接收id列表,期望通过Promise.all批量获取所有id对应的数据。但调用该函数时,Promise.all返回的数组初始长度为0,后续才会被填充,导致无法访问数据,尽管控制台能显示数据。
函数定义如下:
private async _getAssignment(id: string): Promise<IData | undefined> { // 从firebase获取数据 return { id, ...docData } as IData; } public async getAssignments(ids: string[]): Promise<(IData | undefined)[]> { // 当我在map的函数里加console.log时,能正确显示数据 return await Promise.all(ids.map(async (id) => await this._getAssignments(id)); } const assignmentInfo = await getAssignments(['id1', 'id2']);
当修改公共函数仅处理单个id时,两个函数都能正常工作。我熟悉JavaScript,但对Promise的了解仅停留在async/await层面,想知道哪里出错了。
我尝试过用.then()捕获响应、将公共函数设为非异步、先创建Promise列表再用Promise.all解析,结果均为浏览器控制台显示数组初始为空,后续才填充。
我还尝试用for...of循环替代Promise.all/map方案,逐个解析Promise并将结果添加到数组,但数组始终无法被填充,代码如下:
let test1: any = [] for (const id of administrationIds) { const result = await this._getAssignment(id).then((result) => { console.log('resolution', result) // 能打印正确数据 test1.push(result) console.log('test1 is now', test1) // 和map方案出现的情况类似 }) }
1. 函数名拼写错误
公共函数getAssignments中调用的是this._getAssignments(id),但私有函数的实际名称是_getAssignment(单数),多了一个s。这个拼写错误会导致调用不存在的函数,直接破坏了数据获取逻辑。
2. 控制台显示的异步更新特性
你看到的“数组初始为空后续填充”是浏览器控制台的特性:控制台会实时更新引用类型的显示。当你打印数组时,数组当时确实是空的,但后续异步操作完成后数组被修改,控制台会自动更新显示内容,造成视觉上的“延迟填充”错觉。本质问题还是代码逻辑错误导致数据未正确获取。
3. 修正后的代码
批量获取的正确写法
修正函数名拼写,同时简化Promise.all的调用(map返回的Promise数组可直接传入,无需额外await):
public async getAssignments(ids: string[]): Promise<(IData | undefined)[]> { return Promise.all(ids.map(id => this._getAssignment(id))); }
for...of循环的正确写法
避免同时混用await和.then(),改用简洁的异步逻辑:
let test1: (IData | undefined)[] = []; for (const id of administrationIds) { const result = await this._getAssignment(id); console.log('resolution', result); test1.push(result); console.log('test1 is now', test1); }
4. 额外检查点
确保_getAssignment内部从Firebase获取数据的逻辑是正确的异步处理:比如如果使用Firebase的get()方法,需要await获取文档数据,示例如下:
private async _getAssignment(id: string): Promise<IData | undefined> { const doc = await db.collection('assignments').doc(id).get(); if (!doc.exists) return undefined; const docData = doc.data(); return { id, ...docData } as IData; }
验证数据获取
调用getAssignments时,必须确保在await完成后再访问数据:
const assignmentInfo = await getAssignments(['id1', 'id2']); console.log(assignmentInfo); // 此处可获取完整的结果数组
内容的提问来源于stack exchange,提问作者ekelly14

