Nodejs Sequelize recursive async/await

Remco

I'm struggling with a recursive loop and nested create/select statements. I'm receiving an object from a post request with the following structure:

 11.6042
 ---11.6042_01
 ---11.6042_02
 ---11.6042_02
 ---14x10-100
 ------14x10-100_01
 ---14x10-100
 ------14x10-100_01
 ---14x10-100
 ------14x10-100_01
 ---M10-DIN929_14020
 ---M10-DIN929_14020
 ---11.6042_05

Wanted behaviour: travel through the structure recursive, add record to Part table, self join with parent part, join with PartLib table, if no match present create PartLib record and match created record. Process next part.

The problem: part 14x10-100 occurs three times in the structure. I want to create a record for part 14x10-100 in the part_lib table and refer to that record three times. What actually happens is that for each 14x10-100 part a corresponding record in the part_lib table is created in stead of one create and two matches. If I run it again it will match like excpected. I suspect I'm lost in the promise/async await parts of the code.

Below the relevant code. I've removed some attribute mappings for readability. My thoughts behind it: I'm not returning new promises like normal in a async function since Sequelize already returns a promise. When creating a part I'm awaiting (or at least I think so) the partLibController calls to ensure that all matching/creating/joining is done before proceeding to the next part in the structure.

Thanks a bunch!!

Recursive loop

function parseChild(child, modelId, parentId, userId, level) {
    return new Promise((resolve, reject) => {
        partController.create({
            parent_id: parentId
            , name: child.name
        }, { id: userId }).then((part) => {
            resolve({ child: child, level: level });
            
            if (child.children) {
                child.children.forEach(grandChild => {
                    parseChild(grandChild, modelId, part.part_id, userId, level + '---');
                });
            }
        }).catch(error => { console.log(error); });
    }).then((obj) => { console.log(`${obj.level} ${obj.child.name}`); });
}

PartController Create

async function create(partBody, currentUser) {
    let { parent_id, name } = partBody;
    
    const match = await partLibController.match(name);
    let partLibId = null;

    if (match.length == 0) {
        const partLib = await partLibController.createFromPart(partBody, currentUser);
        partLibId = partLib.part_lib_id;
    } else {
        partLibId = match[0].dataValues.part_lib_id
    }

    return ModelAssembly.create({
        parent_id: parent_id
        , name: name
        , part_lib_id: partLibId
    });
}

PartLibController Match

function match(name) {
    return PartLib.findAll({
        where: {
            name: name
        },
    });
}

PartLibController CreateFromPart

function createFromPart(partBody, currentUser) {
    let { name } = partBody;
    
    return PartLib.create({
        name,
    });
}
Remco

Thanks to AKX I've solved the problem: hero

The problem was in the recursive call itself I suppose but here's the working code:

async function parseChild(child, modelId, parentId, userId, level) {
    const body = {
        parent_id: parentId
        , name: child.name
    };
    const ma = await partController.create(body, { id: userId });

    if (child.children) {
        for (const grandChild of child.children) {
            await parseChild(grandChild, modelId, ma.part_id, userId, level + '---');
        }
    }

    return;
}

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related