Search code examples
javascriptnode.jsasync-awaitpromise

Why are async methods not working properly in js?


I have a piece of code that doesn't work properly. I want to define a group of tasks that will fill a field. But these tasks are not done I want to run the following code snippet

const tasks = [];
for (const space of results.data.querySpace) {
    let rows = [];
    // check rows
    if (space.rows) {
        // check component is enable or not
        space.rows = space.rows.filter(
            (item) => item.component.is_enable === true
        );
        rows = space.rows;
    }

    for (const row of rows) {
        // iterate over the components and fetch their list fields
        const component = row.component;
        let task;

        if (component.__typename === "Program_Component") {
            task = async () => {
                component.episodes = await getPrograms(
                    args.Copyright,
                    component.tag_name,
                    graphql
                );
            };
        } else if (component.__typename === "Episode_Component") {
            task = async () => {
                console.log("log") --> dose not run !!!
                component.episodes = await getEpisodes(
                    args.Copyright,
                    component.tag_name,
                    graphql
                );
            };
        } else if (component.__typename === "FullscreenBanner_Component") {
            task = async () => {
                component.episodes = await getEpisodes(
                    args.Copyright,
                    component.tag_name,
                    graphql
                );
            };
        }
        tasks.push(task);
    }
}

const test = await Promise.allSettled(tasks);
console.log(test);
return results.data.querySpace[0];

What is the problem, what should I do to fill the component field correctly?


Solution

  • What you pushed in the tasks array are a bunch of function pointers. You never called those functions, thus they never execute.

    What you need to pass to Promise.allSettled() is an array of promises, not an array of functions.

    You can change this:

    tasks.push(task);
    

    to this:

    tasks.push(task());
    

    So that you're actually calling the functions and then inserting the promise that they return into your array that you then pass the array of promises to Promise.allSettled().

    All of this assumes that getEpisodes() returns a promise that is settled when the underlying operation is completed.


    Here's a little different approach to what you're doing:

    const promises = [];
    for (const space of results.data.querySpace) {
        let rows = [];
        // check rows
        if (space.rows) {
            // check component is enable or not
            space.rows = space.rows.filter(
                (item) => item.component.is_enable === true
            );
            rows = space.rows;
        }
    
        for (const row of rows) {
            // iterate over the components and fetch their list fields
            const component = row.component;
            let promise;
    
            if (component.__typename === "Program_Component") {
                promise = getPrograms(args.Copyright, component.tag_name, graphql).then(r => component.episodes = r);
            } else if (component.__typename === "Episode_Component") {
                promise = getEpisodes(args.Copyright, component.tag_name, graphql).then(r => component.episodes = r);
            } else if (component.__typename === "FullscreenBanner_Component") {
                promise = getEpisodes(args.Copyright, component.tag_name, graphql).then(r => component.episodes = r);
            }
            promises.push(promise);
        }
    }
    
    await Promise.allSettled(promises);
    return results.data.querySpace[0];