ccomann
ccomann

Reputation: 1

Variable data loss after exiting mongo db access Node.js

I'm still a bit new to Node.js and Javascript. I know that javascript is asynchronous by nature, but I can't seem to figure out how to solve this problem. I tried using Promises but that didn't help for this particular case (or maybe I don't know how promises work).

Inside my getChilds() function, I make a search by id in my mongo database and I push the found object to an array called childObjects that I receive by parameter in the getChilds() function.

The object is found and added to the childObjects array. I use console.logs to check that it works. The problem is that when we exit the function, the value for childObjects is undefined.

My getChilds() function:

function getChilds(id, childObjects, res) {
    return new Promise((resolve, reject) => {
        Item.findById(id, function (err, item) {

            if (err) {
                console.log("There's no corresponding item for that id!");
                return (res.send(err));
            }
            console.log("CHILD ITEM:" + item);

            childObjects.push(item);

            console.log("chiild ojects: " + childObjects);
            // return childObjects;
            // res.send(childObjects);
            // return childObjects;
            // res.send(item);

            resolve(item);
            // childObjects.push(item);
        });
    });
}

Thank you for your help!

Upvotes: 0

Views: 44

Answers (3)

Behrooz
Behrooz

Reputation: 11

You are totally right. You are facing two this problem because you used Promise. With Promise, Your code becomes to Non-Blocking code.

I can suggest two solutions to solve this issue.

Scope:

let childObjects;
function getChilds(id, res) {
    return new Promise((resolve, reject) => {
        ...
    });
}

Return the value:

function getChilds(id, childObjects, res) {
    return new Promise((resolve, reject) => {
            ...
            resolve({item: item, childObjects: childObjects);
        });
    });
}

Upvotes: 0

andrea-f
andrea-f

Reputation: 1055

You shouldn't pass childObjects in. You have two options: either you define childObjects at the same level of getChilds. So for instance if you can call this.getChilds then the childObjects array should exist at this.childObjects. Or you resolve(item) and in the callback of the function, where you did this.getChilds(id).then(, you push to the childObjects living in the parent.

Upvotes: 0

trincot
trincot

Reputation: 350310

You should not pass childObjects as argument, nor res. Instead collect the item into childObjects outside of the function:

function getChilds(id) {
    return new Promise((resolve, reject) => {
        Item.findById(id, function (err, item) {
            return err ? reject(err) : resolve(item);
        });
    });
}

Use Promise.all to get your childObjects array:

// Somehow you will get an array of id values, maybe like this:
const childs = item.childs;
// Create promises for each of them
const promises = childs.map(getChilds);
// Promise.all will await all the promises to resolve, putting all items in an array: 
Promise.all(promises).then(childObjects => {
    console.log(childObjects);
    res.send(childObjects);
}).catch(err => {
    console.log('Error occurred', err);
    res.send(err);
});

Note that the plural of "child" is "children" not "childs" ;-)

Upvotes: 1

Related Questions