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);
}));