need to find when all callbacks resolved

Below is a snippet from my javascript function. It’s taking an arbitrary size array of objects travelDataGroups[{}] and iterating over it. Inside of the forEach() I have to call newUser(), which is async, and inside that I have to call loadOtherUsersPayRate() which is asynchronous.
After all the callbacks are resolved and the loop is done, I need to call makeWorkbookDownloadObj(), the catch is it can only be called once, else it corrupts the object.

myGroupWorkReportObj.travelDataGroups.forEach( travelerData =>
{
    // add the pay rate for this user
    const someUser = new User( travelerData.employeeId , function()
    {
        // add the pay rate for this user and project
        const projectId = travelerData.projectId;
            
        const payRate = loadOtherUsersPayRate( projectId, someUser )
            .then( payRate =>
            {
                //create a row of travel data
                const rowOfData = [
                    travelerData.firstName,
                    travelerData.lastName,
                    travelerData.travelHours,
                    financial( payRate.pay / 2 )
                ];

                // push the row of data into the sheet
                thisSheet.data.push( rowOfData );

                // need to only call this once, when all callbacks are resolved
                // makeWorkbookDownloadObj( workbookObj );
        });
});

EDIT final working code:

const userPromises = [];

// wrap the User class in a Promise
var aUserPromise = ( travelerData ) =>
{
    return new Promise( ( resolve, reject ) =>
    // new User( employeeId, ( someUser ) =>
    {
        // return new Promise( ( resolve, reject ) =>
        new User( travelerData.employeeId, ( someUserObj ) =>
        {
            // add the pay rate for this user and project
            loadOtherUsersPayRate( travelerData.projectId, someUserObj )
            .then( payRate =>
            {
                //create a row of travel data
                const rowOfData = [
                    travelerData.firstName,
                    travelerData.lastName,
                    travelerData.travelHours,
                    financial( payRate.pay / 2 )
                ];

                // push the row of data into the sheet
                thisSheet.data.push( rowOfData );

                resolve();
            } );
        } );
    } );
};

myGroupWorkReportObj.travelDataGroups.forEach(( travelerData ) =>
{
    // add the pay rate for this user
     ** this line would push the function, but not execute it (until later),
     ** so did in two lines as below
    // userPromises.push(aUserPromise(travelerData)); 

    var myRun = aUserPromise( travelerData );
    userPromises.push( myRun );
});

Promise.allSettled( userPromises )
.then( ()=>
{
    makeWorkbookDownloadObj( workbookObj )
});

Answer

Following your comment and using Promise ALL and same pattern used by previous answer:

const userPromises = [];
myGroupWorkReportObj.travelDataGroups.forEach( travelerData =>
    {
// add the pay rate for this user
        userPromises.push(new User( travelerData.employeeId , function()
        {
            // add the pay rate for this user and project
            const projectId = travelerData.projectId;
    
            const payRate = loadOtherUsersPayRate( projectId, someUser )
                .then( payRate =>
                {
                    //create a row of travel data
                    const rowOfData = [
                        travelerData.firstName,
                        travelerData.lastName,
                        travelerData.travelHours,
                        financial( payRate.pay / 2 )
                    ];
    
                    // push the row of data into the sheet
                    thisSheet.data.push( rowOfData );
                })
        }));
    });
Promise.all(userPromises).then(() => {
    makeWorkbookDownloadObj( workbookObj );
});

The true promises needing go be resolved are the users creation.