Home > Software design >  Item doesn't want to be pushed into an array
Item doesn't want to be pushed into an array

Time:06-21

I am developing a discord bot that allows you to mine for resources, but I can't get the code to work. It's logging the actual items, but it just doesn't add the items to the array, which is why I can't map it into a string.

Code:

module.exports.addItem = async (client, user, item, amount, interaction) => {
    if(!client instanceof Client) throw new Error("Client is not an instance of Discord.js Client");
    if(!user instanceof User) throw new Error("User is not an instance of Discord.js User");
    if(!item) throw new Error("Item is not defined");
    if(!amount) throw new Error("Amount is not defined");
    if(typeof amount !== "number") throw new Error("Amount is not a number");
    if(!interaction) throw new Error("Interaction is not defined");
    if(!interaction instanceof Interaction) throw new Error("Interaction is not an instance of Discord.js Interaction");

    const userFound = await client.database.user.findOne({ userID: user.id });
    if(!userFound) return interaction.followUp({ content: `You haven't started your journey yet!` });

    const itemFound = userFound.inventory.find(i => i.name === item.name);
        if(!itemFound) {
            await client.database.user.findOneAndUpdate(
                {
                    userID: user.id,
                }, {
                    userID: user.id,
                    $push: {
                        inventory: {
                            name: item.name,
                            amount,
                            category: item.category
                        }
                    }
                } , {
                    upsert: true,
            });
        } else {
            await client.database.user.findOneAndUpdate(
                {
                    userID: user.id,
                }, {
                    userID: user.id,
                    $pull: {
                        inventory: {
                            name: item.name
                        }
                    } 
                } , {
                    upsert: true,
            });
                
            await client.database.user.findOneAndUpdate(
                {
                    userID: user.id,
                }, {
                    userID: user.id,
                    $push: {
                       inventory: {
                            name: item.name,
                            amount: item.amount   amount,
                            category: item.category
                        }
                    }
                } , {
            upsert: true,
        });
    }
    return { name: item.name, amount, category: item.category };
}

module.exports.dropItem = async (client, user, category, interaction) => {
    if(!client instanceof Client) throw new Error("Client is not an instance of Discord.js Client");
    if(!user instanceof User) throw new Error("User is not an instance of Discord.js User");
    if(!category) throw new Error("Category is not defined");
    if(typeof category !== "string") throw new Error("Category is not a string");

    let droppedItems = [];
    
    for (const item of client.items) {
        for(let i = 0; i < client.items.length; i  ) {
            if(!client.items[i].category === category) return;
        }

        const dropAmount = Math.floor((Math.random() * 3)   1);
        const dropChance = Math.floor(Math.random() * 100);
        if(dropChance > item.dropChance) return;

        const itemDropped = await this.addItem(client, user, item, dropAmount, interaction)
        console.log(itemDropped); // This logs the item correctly

        droppedItems.push(itemDropped);
    }

    return droppedItems; // This always returns "undefined"
}

Expected result: An array with objects, each object containing a name, amount and category value;

Actual result: Console-logging the array returns "undefined"

I have tried awaiting the push, making the array a constant and more small things like that. Could it be because the array isn't in the loop?

CodePudding user response:

The problem is probably that you have several return statements in your dropItem function that are returning undefined.

For example if(dropChance > item.dropChance) return;

A simple function to illustrate this is:

const doSomething = () => {
    const arr = [1, 2, 3]
    for (const num of arr) {
        if (num !== 10) return
  }
    return 'done'
}

You are saying that you would expect the above function to return "done", but it will actually return undefined.

I think maybe you want to use break instead of return, but not sure exactly what behaviour you are expecting. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/break

CodePudding user response:

Since you are awaiting a call within the for loop, you will need to await the entire loop as well. You can do this with await Promise.all(<<ARRAY OF PROMISES>>).

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

So you'd do something like

let droppedItems = [];
await Promise.all(client.items.map(async (item) => {
        for(let i = 0; i < client.items.length; i  ) {
            if(!client.items[i].category === category) return;
        }

        const dropAmount = Math.floor((Math.random() * 3)   1);
        const dropChance = Math.floor(Math.random() * 100);
        if(dropChance > item.dropChance) return;

        const itemDropped = await this.addItem(client, user, item, dropAmount, interaction)
        console.log(itemDropped); // This logs the item correctly

        droppedItems.push(itemDropped);
    }));
  • Related