【问题标题】:Node Js - SyntaxError: await is only valid in async functionNode Js - SyntaxError: await 仅在异步函数中有效
【发布时间】:2020-09-11 21:47:08
【问题描述】:

我在 service.js 文件中有以下代码。

exports.getSeminarDetailsById = async function (seminarId) {
try {
    let SeminarList = [];
    var seminarData = await SeminarRepository.getSeminarDetailsById(seminarId);
    if (seminarData && seminarData.length > 0) {
        let userIdList = [...new Set(seminarData.map(x => x.user_id))];
        if (userIdList && userIdList.length > 0) {
            let userDetails = await EmployeeRepository.getEmployeeDetailsByUserIds(userIdList);
            if (userDetails && userDetails.length > 0) {
                seminarData.forEach(element => {
                    let seminarDetail;
                    let userName = userDetails.filter(x => x.user_id == element.user_id).map(x => x.userfullname)[0];
                    let categoryName;
                    if (element.category_id == 1)
                        categoryName = AppConstants.seminarCategoryName.TECHNICAL;
                    else
                        categoryName = AppConstants.seminarCategoryName.NONTECHNICAL;

                    seminarDetail = new SeminarTrackerDetails(element, userName, categoryName);
                    await mapAttachmentWithSeminar(seminarId, seminarDetail);
                    console.log("second", seminarDetail);
                    SeminarList.push(seminarDetail);
                });
            }
        }
    }
    return SeminarList;
} catch (err) {
    console.log(err);
    throw err;
}
}

await mapAttachmentWithSeminar(seminarId, seminarDetail); 出现此错误,它在以下同一文件中定义。

async function mapAttachmentWithSeminar(seminarId, seminarDetail) {
var seminarAttachmentDetails = await SeminarRepository.getSeminarAttachmentDetailsById(seminarId);
  if (seminarAttachmentDetails && seminarAttachmentDetails.length > 0) {
    let AttachmentDetails = [];
    seminarAttachmentDetails.forEach(element => {
        let attachmentDetails = new SeminarAttachmentDetails(element);
        AttachmentDetails.push(attachmentDetails);
    });
    seminarDetail.SeminarAttachmentDetails = AttachmentDetails;
  }
  else {
    seminarDetail.SeminarAttachmentDetails = null;
    console.log("first", seminarDetail);
  }
}

如果我删除 await 函数,那么在执行函数 mapAttachmentWithSeminar() 之前将首先执行 console.log("second", seminarDetail);。这样从该函数返回的SeminarAttachmentDetails 的值将被遗漏,如下所示:

这是预期的输出。

【问题讨论】:

  • 错误很明显。改写这个问题,让它更简洁地表达为“我有 X 但需要输出 Y”

标签: javascript node.js


【解决方案1】:

您可以使用经典的for 循环而不是使用.forEach

for(let i = 0; i < seminarData.length; i++){
    let element = seminarData[i];
    let seminarDetail;
    let userName = userDetails.filter(x => x.user_id == element.user_id).map(x => x.userfullname)[0];
    let categoryName;
    if (element.category_id == 1)
        categoryName = AppConstants.seminarCategoryName.TECHNICAL;
    else
        categoryName = AppConstants.seminarCategoryName.NONTECHNICAL;

    seminarDetail = new SeminarTrackerDetails(element, userName, categoryName);
    await mapAttachmentWithSeminar(seminarId, seminarDetail);
    console.log("second", seminarDetail);
    SeminarList.push(seminarDetail);
}

【讨论】:

    【解决方案2】:

    首先,您使用了错误的异步等待。您在非异步函数的范围内等待。 这里:

     seminarData.forEach(element => {
                    let seminarDetail;
                    let userName = userDetails.filter(x => x.user_id == element.user_id).map(x => x.userfullname)[0];
                    let categoryName;
                    if (element.category_id == 1)
                        categoryName = AppConstants.seminarCategoryName.TECHNICAL;
                    else
                        categoryName = AppConstants.seminarCategoryName.NONTECHNICAL;
    
                    seminarDetail = new SeminarTrackerDetails(element, userName, categoryName);
                    await mapAttachmentWithSeminar(seminarId, seminarDetail);
                    console.log("second", seminarDetail);
                    SeminarList.push(seminarDetail);
                });
    

    你应该有这个

     // here you have the SeminarList but promisified
     // with the form Promise<SeminarListItem>[]
     // to get the values out of the promises you have to await this array     
        const promisifiedSeminarList = seminarData.map((element)=>{
             let userName = userDetails.filter(x => x.user_id == element.user_id).map(
                x => x.userfullname)[0]
             );
    
            const categoryName = elemenet.category_id == 1
              ? AppConstants.seminarCategoryName.TECHNICAL
              : AppConstants.seminarCategoryName.NONTTECHNICAL;
    
           const seminarDetail = new SeminarTrackerDetails(element, userName, categoryName);
           return mapAttachmentWithSeminar(seminarId, seminarDetail);
        });
      // now
       const seminarList = await Promise.all(promisifiedSeminarList);
    

    为此,您需要函数 mapAttachmentWithSemniar 返回一个未发生的值

    【讨论】:

      【解决方案3】:

      每个嵌套函数都应该声明为async 以及父函数。 在您的情况下,此声明在嵌套级别之一中丢失,请注意这部分代码

      seminarData.forEach(async element => {
      //                  ^^^^ async missed here
       let seminarDetail;
       let userName = userDetails.filter(x => x.user_id == element.user_id).map(x => x.userfullname)[0];
       let categoryName;
       if (element.category_id == 1)
        categoryName = AppConstants.seminarCategoryName.TECHNICAL;
       else
        categoryName = AppConstants.seminarCategoryName.NONTECHNICAL;
       seminarDetail = new SeminarTrackerDetails(element, userName, categoryName);
       await mapAttachmentWithSeminar(seminarId, seminarDetail); 
       console.log("second", seminarDetail); 
       SeminarList.push(seminarDetail);
      });
      

      【讨论】:

      • 以上代码没有返回任何错误,而是返回空列表
      • 该代码不会改变您的应用程序的逻辑,它只会修复您遇到的错误。
      • 这是正确答案。不要因为您的代码不起作用而对其投反对票。
      猜你喜欢
      • 1970-01-01
      • 2020-12-07
      • 2020-04-29
      • 1970-01-01
      • 1970-01-01
      • 2020-07-31
      • 1970-01-01
      • 2021-11-04
      • 2020-09-07
      相关资源
      最近更新 更多