You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在async函数中获取异步回调内的数组变量并返回至控制器

异步Excel导入错误数据无法返回Controller的问题

在Service类的async importExcel函数中,我声明了errorData数组存储Excel导入的错误信息:

  • 在readXlsxFile的then回调内可以正常访问该数组
  • 但在回调外的函数末尾无法获取数组内容,无法返回给Controller
  • 尝试用setTimeout能打印数组,但依然无法返回给Controller

相关代码

Service类代码

// service class
async importExcel(userId, file){
  const business = await this.getBusinessByUserId(Types.ObjectId(userId));
  let errorData = [];
  readXlsxFile(file, {schema}).then(async ({rows, errors}) => {
    if(errors.length === 0){
      await this.excelUploadQueue.add({
        rows,
        business
      })
    }
    errors.forEach((error) => {
      const errors = { // 注意此处变量名与外层errors重复,易引发混淆
        column: error.column,
        value: error.value,
        reason: error.reason,
      }
      errorData.push(errors)
    });
    console.log(errorData); // 此处可正常访问errorData
  }) 
  console.log(errorData); // 此处无法获取到正确数据
  return errorData; // 无法返回正确数据给Controller
}

Controller类代码

// controller
@UseGuards(JwtAuthGuard)
@UseInterceptors(FileInterceptor('file'
, {
  storage: diskStorage({
    destination: './csv',
    filename: (req, file, cb) => {
      const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
      cb(null, file.fieldname + '-' + uniqueSuffix + "-" + file.originalname)
    }
  })
}
))
@Post('/import-excel/employee')
@ApiOperation({summary: 'upload employee data via excel'})
async uploadExcel(
  @UploadedFile() file: Express.Multer.File,
  @Request() req
  ){
    const { id: userId } = req.user;
    return await this.businessService.importExcel(userId, file.path);
}

尝试的setTimeout代码

setTimeout(() => {
  console.log(errorData) // 能打印数组,但无法返回给Controller
}, 100);

问题原因与解决方案

问题核心是异步操作时序问题:readXlsxFile是异步函数,then回调会在后续事件循环中执行,但函数末尾的return errorData会在回调执行前就执行,因此返回的是空数组。setTimeout只是延迟打印,无法改变函数返回的时机。

解决方法是用await替代then,将异步操作改为同步写法,确保在返回数据前完成错误信息的收集:

async importExcel(userId, file){
  const business = await this.getBusinessByUserId(Types.ObjectId(userId));
  let errorData = [];
  // 用await等待readXlsxFile执行完成
  const {rows, errors} = await readXlsxFile(file, {schema});
  
  if(errors.length === 0){
    await this.excelUploadQueue.add({
      rows,
      business
    })
  }
  
  // 遍历错误信息,修改变量名避免与外层errors冲突
  errors.forEach((error) => {
    const errorItem = {
      column: error.column,
      value: error.value,
      reason: error.reason,
    }
    errorData.push(errorItem);
  });
  
  console.log(errorData); // 此处可正常获取数据
  return errorData; // 现在能正确返回给Controller
}

额外优化点

  • 原代码中forEach内部的变量errors与外层的errors重名,建议改为errorItem这类清晰的命名
  • 使用await后代码逻辑更线性,可读性更强,也避免了回调嵌套的问题

内容的提问来源于stack exchange,提问作者Abhay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 17:57:24