简体   繁体   中英

How to return data in nested async/await function

I am using the node-vibrant api to retrieve a colour palette, but it seems to return it too late even though I've put async-await into the code.

It is definitely not waiting as the console.log I put in below shows modified->transformed->new data .

I'm not sure what I'm missing or accidentally adding since I've made it confusing the numerous times I've broken the code down.

if(artist == 'picasso'){
   transformedData = await transformPage(data, artistObject)
}
export async function transformPage(pageData: PageData, artist: any){
    pageData.components.forEach(async function(component){
        if(component == 'header'){
            await transformHeader(component.attributes, artist);
        }
    });

    console.log('transformed');

    return pageData;
}

function transformHeader(attributesFragment: any,  artist: any) {
    generateColourPalette(attributesFragment['container'], artist).then(modified => attributesFragment['container'] = modified);

    console.log('modified');
        
    return attributesFragment;
}

async function generateColourPalette(container: any,  artist: any) {
    const albumCover = artist['image']['url'];
    
    const v = new Vibrant(albumCover);
    const palette = (await v.getPalette()).Vibrant?.hex;
    container['backgroundColour']= palette;

    console.log('new container'); 
    
    return container;
}

To make things more clear I tried to comment out the code and replace them with my suggestions

export async function transformPage(pageData: PageData, artist: any){
    // Instead of the forEach you need to use the Promise with a map function to properly handle nested async
    // pageData.components.forEach(async function(component){
    //     if(component == 'header'){
    //         await transformHeader(component.attributes, artist);
    //     }
    // });
    await Promise.all(pageData.components.map(async function(component){
        if(component == 'header'){
            await transformHeader(component.attributes, artist);
        }
    }));
    console.log('transformed');

    return pageData;
}
// Here you need to add async in front of you function
// function transformHeader(attributesFragment: any,  artist: any) {
async function transformHeader(attributesFragment: any,  artist: any) {
    // for constency in your code keep using the async/await 
    // generateColourPalette(attributesFragment['container'], artist).then(modified => attributesFragment['container'] = modified);
    const modified = await generateColourPalette(attributesFragment['container'], artist)
    attributesFragment['container'] = modified

    console.log('modified');
        
    return attributesFragment;
}

async function generateColourPalette(container: any,  artist: any) {
    const albumCover = artist['image']['url'];
    
    const v = new Vibrant(albumCover);
    const palette = (await v.getPalette()).Vibrant?.hex;
    container['backgroundColour']= palette;

    console.log('new container'); 
    
    return container;
}

Currently “transformPage” fires off many asynchronous function calls but these aren't awaited, so the function returns immediately. You can either await within a “for... of” loop or await many requests concurrently. Some helpful information can be found here:

Using async/await with a forEach loop

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