Looping through an array getting input each iteration

I'm trying to loop through an array to get input each iteration of the loop. The issue I'm running into right now is the loop goes right to the end. How can I delay this so that I can get the input at each step of the way rather than instantly jumping to the end? My code is:
await interaction.reply(`The following players rolled the same highest number and need to select a swing: ${toFix.join(", ")}`);
toFix.forEach(async player => {
buttons = [];
indexes = [];
battleState[player].rolls.forEach((roll, i) => {
if (roll === Math.max(...battleState[player].rolls)) {
indexes.push(i);
buttons.push(new ButtonBuilder().setLabel(battleState[player].colors[i]).setStyle(ButtonStyle.Primary).setCustomId(`tie-${i}`));
}
});
row = new ActionRowBuilder().addComponents(...buttons);
response = await interaction.editReply({content : `${player} rolled ${battleState[player].rolls.map((y, i) => `\`${battleState[player].colors[i]}: ${y}\``).join(", ")}\nSelect one of the following:`,
components: [row],
});

filter = (i) => i.user.id === interaction.user.id;

collector = response.createMessageComponentCollector({
componentType: ComponentType.Button,
filter,
time: 15_000,
});

collector.on('collect', async (i) => {
console.log(i.customId);
index = i.customId.split("-")[1];
battleState[player].swing = [battleState[player].colors[index], battleState[player].rolls[index]];
fs.writeFileSync(`./battles/${interaction.channel.id}.json`, JSON.stringify(battleState), { flag: 'w' }, function(err) {
if (err)
return console.error(err);
});
interaction.editReply({content:`${player} rolled ${battleState[player].rolls.map((y, i) => `\`${battleState[player].colors[i]}: ${y}\``).join(", ")} and was added to the battle with a swing of \`${battleState[player].swing[0]}: ${battleState[player].swing[1]}\``, components: []});
collector.stop();
});

collector.on('end', async (collected, reason) => {
if (reason === 'time') {
index = indexes[0];
battleState[player].swing = [battleState[player].colors[index], battleState[player].rolls[index]];
fs.writeFileSync(`./battles/${interaction.channel.id}.json`, JSON.stringify(battleState), { flag: 'w' }, function(err) {
if (err)
return console.error(err);
});
interaction.editReply({content:`Time is up, ${player} rolled ${battleState[player].rolls.map((y, i) => `\`${battleState[player].colors[i]}: ${y}\``).join(", ")} and has been added to the battle with their swing set to \`${battleState[player].swing[0]}: ${battleState[player].swing[1]}\``,components: []});
}
});
});
await interaction.reply(`The following players rolled the same highest number and need to select a swing: ${toFix.join(", ")}`);
toFix.forEach(async player => {
buttons = [];
indexes = [];
battleState[player].rolls.forEach((roll, i) => {
if (roll === Math.max(...battleState[player].rolls)) {
indexes.push(i);
buttons.push(new ButtonBuilder().setLabel(battleState[player].colors[i]).setStyle(ButtonStyle.Primary).setCustomId(`tie-${i}`));
}
});
row = new ActionRowBuilder().addComponents(...buttons);
response = await interaction.editReply({content : `${player} rolled ${battleState[player].rolls.map((y, i) => `\`${battleState[player].colors[i]}: ${y}\``).join(", ")}\nSelect one of the following:`,
components: [row],
});

filter = (i) => i.user.id === interaction.user.id;

collector = response.createMessageComponentCollector({
componentType: ComponentType.Button,
filter,
time: 15_000,
});

collector.on('collect', async (i) => {
console.log(i.customId);
index = i.customId.split("-")[1];
battleState[player].swing = [battleState[player].colors[index], battleState[player].rolls[index]];
fs.writeFileSync(`./battles/${interaction.channel.id}.json`, JSON.stringify(battleState), { flag: 'w' }, function(err) {
if (err)
return console.error(err);
});
interaction.editReply({content:`${player} rolled ${battleState[player].rolls.map((y, i) => `\`${battleState[player].colors[i]}: ${y}\``).join(", ")} and was added to the battle with a swing of \`${battleState[player].swing[0]}: ${battleState[player].swing[1]}\``, components: []});
collector.stop();
});

collector.on('end', async (collected, reason) => {
if (reason === 'time') {
index = indexes[0];
battleState[player].swing = [battleState[player].colors[index], battleState[player].rolls[index]];
fs.writeFileSync(`./battles/${interaction.channel.id}.json`, JSON.stringify(battleState), { flag: 'w' }, function(err) {
if (err)
return console.error(err);
});
interaction.editReply({content:`Time is up, ${player} rolled ${battleState[player].rolls.map((y, i) => `\`${battleState[player].colors[i]}: ${y}\``).join(", ")} and has been added to the battle with their swing set to \`${battleState[player].swing[0]}: ${battleState[player].swing[1]}\``,components: []});
}
});
});
As of now, when I input 2 players, foo and bar, in the array in order, the message automatically skips to bar and whichever button I click for bar is updated in by battleState for foo as well.
11 Replies
d.js toolkit
d.js toolkit9mo ago
- What's your exact discord.js npm list discord.js and node node -v version? - Not a discord.js issue? Check out #other-js-ts. - Consider reading #how-to-get-help to improve your question! - Explain what exactly your issue is. - Post the full error stack trace, not just the top part! - Show your code! - Issue solved? Press the button!
Squid
Squid9mo ago
Msot likely, using promisified collectors like await response.awaitMessageComponent(...) and for...of loops instead of .forEach() callbacks would make this possible Right now, each iteration of toFix.forEach() just creates collectors, and once that is sucessfully done, it repeats by creating collectors with the next player
Zela
ZelaOP9mo ago
what does await message component do?
Squid
Squid9mo ago
It resolves to a message component interaction that was received on the message, or it rejects if it didnt collect one in your specified time It would be blocking since
a;
const i = await response.awaitMessageComponent(...);
b;
a;
const i = await response.awaitMessageComponent(...);
b;
Would make it so b never runs until i is collected, and
for (const num of [1, 2]) {
a;
const i = await response.awaitMessageComponent(...);
b;
}
for (const num of [1, 2]) {
a;
const i = await response.awaitMessageComponent(...);
b;
}
would make it so it iterates over 1, collects i, and then starts to iterate over 2 to collect a new i
d.js docs
d.js docs9mo ago
:guide: Popular Topics: Collectors - Interaction collectors > Await message component read more
Zela
ZelaOP9mo ago
so I use awaitMessageComponent in place of createMessageComponentCollector?
Squid
Squid9mo ago
You'll need to adjust more than only that, but that's right
Zela
ZelaOP9mo ago
so instead of
const collector = response.createMessageComponentCollector({
componentType: ComponentType.Button,
filter,
time: 15_000,
});
const collector = response.createMessageComponentCollector({
componentType: ComponentType.Button,
filter,
time: 15_000,
});
I do something like
response.awaitMessageComponent({componentType: ComponentType.Button, filter, time: 15_000}).then(i => {
//do stuff
interaction.editReply(...)
}).catch(err => other stuff);
response.awaitMessageComponent({componentType: ComponentType.Button, filter, time: 15_000}).then(i => {
//do stuff
interaction.editReply(...)
}).catch(err => other stuff);
me changing it to awaitMessageComponent has caused the same issue
response.awaitMessageComponent({filter, componentType: ComponentType.Button, time: 15_000})
.then(i => {
const index = i.customId.split("-")[1];
battleState[player].swing = [battleState[player].colors[index], battleState[player].rolls[index]];
fs.writeFileSync(...);
interaction.editReply(...)
.catch(err => {
index = indexes[0];
battleState[player].swing = [battleState[player].colors[index], battleState[player].rolls[index]];
fs.writeFileSync(`...);
interaction.editReply(...);
});
response.awaitMessageComponent({filter, componentType: ComponentType.Button, time: 15_000})
.then(i => {
const index = i.customId.split("-")[1];
battleState[player].swing = [battleState[player].colors[index], battleState[player].rolls[index]];
fs.writeFileSync(...);
interaction.editReply(...)
.catch(err => {
index = indexes[0];
battleState[player].swing = [battleState[player].colors[index], battleState[player].rolls[index]];
fs.writeFileSync(`...);
interaction.editReply(...);
});
Squid
Squid9mo ago
Have you considered using await
Zela
ZelaOP9mo ago
I might be slow wait where do I even use await here following the guide on the website it doesnt say where to put await nor does it use await itself ok new error, it waits but when I come to second iteration it simply says this interaction failed I put the await in front of the response.awaitMessageComponent(...) the error seems to be because I am not deferring the message reply or update, so I cannot track it past the first loop I have 0 clue how to approach that When I interact with it instantly, the second loop comes through but cannot be interacted with but when I take a while, it doesn't come through at all So to put things together, the current state of the code is this:
for(const thing in arr) {
const response = await interaction.edit(...)
const filter = (i) => {
i.deferUpdate();
return i.user.id === interaction.user.id;
};
await response.awaitMessageComponent({filter, componentType: ComponentType.Button, time: 15_000})
.then(i => {
//stuff to do
i.editReply(reply);
})
.catch(err => {
// on time out
i.editReply(reply);
});
}

for(const thing in arr) {
const response = await interaction.edit(...)
const filter = (i) => {
i.deferUpdate();
return i.user.id === interaction.user.id;
};
await response.awaitMessageComponent({filter, componentType: ComponentType.Button, time: 15_000})
.then(i => {
//stuff to do
i.editReply(reply);
})
.catch(err => {
// on time out
i.editReply(reply);
});
}

And it runs the first iteration fine, but does not even look at the second iteration Error thrown is:
requestBody: { files: undefined, json: { type: 6 } },
rawError: { message: 'Unknown interaction', code: 10062 },
code: 10062,
status: 404,
method: 'POST',
url: 'https://discord.com/api/v10/interactions/1218688061605543946/aW50ZXJhY3Rpb246MTIxODY4ODA2MTYwNTU0Mzk0NjpmbHZWQzJCanFBbE5US0VuQTRLbmhwVjJpU0ZOTGZ6S0dTbGpLZXJNOEFucU1MRVVDWUtuS0Vabmd6UW5FNERCUHRST0ExTG1iU0M1THZPV1VHSGRJMlpKWGJjUW9vNGVLWG9vaEtEdXl4NDc4am5vWnFSWEFVOXdTd2RBcndmcQ/callback'
}
requestBody: { files: undefined, json: { type: 6 } },
rawError: { message: 'Unknown interaction', code: 10062 },
code: 10062,
status: 404,
method: 'POST',
url: 'https://discord.com/api/v10/interactions/1218688061605543946/aW50ZXJhY3Rpb246MTIxODY4ODA2MTYwNTU0Mzk0NjpmbHZWQzJCanFBbE5US0VuQTRLbmhwVjJpU0ZOTGZ6S0dTbGpLZXJNOEFucU1MRVVDWUtuS0Vabmd6UW5FNERCUHRST0ExTG1iU0M1THZPV1VHSGRJMlpKWGJjUW9vNGVLWG9vaEtEdXl4NDc4am5vWnFSWEFVOXdTd2RBcndmcQ/callback'
}
when I try to click the second body
royc
royc9mo ago
i thought you can't edit interactions after 2-3 seconds without deferring them
Want results from more Discord servers?
Add your server