简体   繁体   中英

Node Js - SyntaxError: await is only valid in async function

I have below code in service.js file.

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;
}
}

Here error comes on await mapAttachmentWithSeminar(seminarId, seminarDetail); and it is defined in the same file as below.

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);
  }
}

If I remove the await function, then console.log("second", seminarDetail); will be executed first before executing the function mapAttachmentWithSeminar() . So that the value of SeminarAttachmentDetails returning from that function will be missed as shown below:

在此处输入图像描述

This was the expected output.

在此处输入图像描述

Instead of using .forEach you could go with a classic for loop

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);
}

every nested function should be declared as async as well as parent's. in your case this declaration is missed in one of nesting level, pay attention on this part of code

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);
});

First you are using wrong async await. You are awaiting inside the scope of a function which is not async. Here:

 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);
            });

You should have this

 // 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);

For that to work you need that the function mapAttachmentWithSemniar returns a value which is not happening

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM