我正在尝试为不和谐的机器人发出轮询命令,其中用户在第一个命令中选择多个选项(即“!poll 4”),然后选择问题和选项。我在让机器人等待响应之前遇到了一些问题,该机器人将继续前进到循环中的下一个选项。当我尝试在循环中使用await时,它说我不能使用await,因为它不是异步函数,但我认为它是异步函数。我对此没有经验,所以我确定这是一个简单的错误或可能是多个错误。如果有人可以给我一些建议,使循环按预期方式工作,并要求每个选项,我将不胜感激。还有一种方法可以添加if语句来为嵌入添加addFields?这是我的代码:
const Discord = module.require('discord.js');
module.exports = {
name: 'poll',
async execute(message, args) {
function isNumber(n) { return !isNaN(parseFloat(n)) && !isNaN(n - 0) }
if(isNumber(args[1])){
if(args[1]<2) return message.channel.send('Please choose a higher number of options for the poll :)');
if(args[1]>10) return message.channel.send('Please choose a lower number of options for the poll :)');
const filter = response => {
if(!response.author.bot) return response;
};
var question;
var options;
message.channel.send('What question would you like to ask?').then(() => {
message.channel.awaitMessages(filter, { max: 1, time: 15000})
.then(collected => {
question = `${collected.first()}?`;
message.channel.send('Question: ' + question);
for (var i = 0; i < args[1]; i++) {
message.channel.send('What is option ' + (i + 1) + '?').then(() => {
message.channel.awaitMessages(filter, { max: 1, time: 15000})
.then(collected => {
options[i] = collected.first;
message.channel.send(`Option ${i}: ${options[i]}`);
})
.catch(collected => {
message.channel.send('Poll has timed out.');
});
})
}
})
.catch(collected => {
message.channel.send('Poll has timed out.');
});
const embed = new Discord.MessageEmbed()
.setColor(3447003)
.setTitle(question)
.setDescription('choose an option')
/*
if (options[0]) .addField('1️⃣:' + option[0])
if (options[1]) .addField('2️⃣:' + option[1])
if (options[2]) .addField('3️⃣:' + option[2])
if (options[3]) .addField('4️⃣:' + option[3])
if (options[4]) .addField('5️⃣:' + option[4])
if (options[5]) .addField('6️⃣:' + option[5])
if (options[6]) .addField('7️⃣:' + option[6])
if (options[7]) .addField('8️⃣:' + option[7])
if (options[8]) .addField('9️⃣:' + option[8])
if (options[9]) .addField('?:' + option[9])
*/
message.channel.send(embed).then(embedMessage => {
if (options[0]) embedMessage.react('1️⃣');
if (options[1]) embedMessage.react('2️⃣');
if (options[2]) embedMessage.react('3️⃣');
if (options[3]) embedMessage.react('4️⃣');
if (options[4]) embedMessage.react('5️⃣');
if (options[5]) embedMessage.react('6️⃣');
if (options[6]) embedMessage.react('7️⃣');
if (options[7]) embedMessage.react('8️⃣');
if (options[8]) embedMessage.react('9️⃣');
if (options[9]) embedMessage.react('?');
});
});
}
}
}
答案 0 :(得分:0)
由于您说过要在循环中使用await
,所以让我从您的代码段中提取其中包含的功能,对其进行一些格式化,然后尝试做一些解释。免责声明:我不是专家,所以我也在学习。
.then(collected => {
question = `${collected.first()}?`;
message.channel.send(`Question: ${question}`);
for (var i = 0; i < args[1]; i++) {
message.channel.send(
`What is option ${i + 1}?`
).then(() => {
message.channel.awaitMessages(filter, {
"max": 1,
"time": 15000,
}).then(collected => {
options[i] = collected.first;
message.channel.send(`Option ${i}: ${options[i]}`);
}).catch(collected => {
message.channel.send("Poll has timed out.");
});
});
}
});
但是在此之前,由于第一个内部.then()
仍返回Promise
,因此您可以在外部范围内链接第二个内部.then()
以避免嵌套太深,并留下一个最后一个.catch()
。在此注意,将catch的参数称为error
之类可能更准确。因此,这是新的代码段:
.then(collected => {
question = `${collected.first()}?`;
message.channel.send('Question: ' + question);
for (var i = 0; i < args[1]; i++) {
message.channel.send(
`What is option ${i + 1}?`
).then(() => {
message.channel.awaitMessages(filter, {
"max": 1,
"time": 15000,
});
}).then(collected => { // Change .then() chaining
options[i] = collected.first;
message.channel.send(`Option ${i}: ${options[i]}`);
}).catch(error => { // Change parameter name
message.channel.send("Poll has timed out.");
});
}
})
现在正在发生的是,每个迭代立即一次又一次地运行。您.send()
收到一堆消息,每条消息都返回一个Promise
,然后离开Promise
,您将一个回调函数传递给.then()
,每个Promise
运行一次解析为Message
。该回调隐式返回.awaitMessages()
的结果,这也是一个承诺,并且一旦解决,下一个.then()
中的下一个回调将使用解析为作为传入的前一个承诺的值运行。论据,等等。
好的,因此您想在整个Promise链中完成处理并解决问题,然后再进行下一个迭代,对吗?您可以使用await
关键字来暂停相关匿名函数的进度,直到其关联的基于promise的操作得以解决或拒绝为止。问题是该函数必须用async
关键字标记,而在您的代码中,实际上并非如此,您只是在使用Promise
和回调函数(关于“但是我认为这是一个异步功能”)。因此,让我们添加上述两个关键字:
.then(async collected => { // Mark as async
question = `${collected.first()}?`;
message.channel.send('Question: ' + question);
for (var i = 0; i < args[1]; i++) {
await message.channel.send( // Wait for this entire Promise chain to resolve before proceeding
`What is option ${i + 1}?`
).then(() => {
message.channel.awaitMessages(filter, {
"max": 1,
"time": 15000,
});
}).then(collected => {
options[i] = collected.first;
message.channel.send(`Option ${i}: ${options[i]}`);
}).catch(error => {
message.channel.send("Poll has timed out.");
});
}
})
这应该会导致您期望的行为,尽管我自己没有运行它,但是我的编辑可能存在语法错误。如果我做错了,请发表评论。
您可以在此处阅读更多信息: