[英]How to wait for this function to finish?
在将数据发送到控制台之前,我需要等待映射 function 完成。 我知道它与 Promise 有关。 我已经尝试了几个小时,即使在阅读了很多关于 Promise 和异步函数的内容之后,我也无法让它工作......
async function inactiveMemberWarner() {
var msg = "```javascript\nI have sent warnings to members that have been inactive for 2 weeks.\n\n"
var inactiveMembers = '';
var count = 0;
var guildMembers = client.guilds.find(g => g.name === mainGuild).members;
const keyPromises = await guildMembers.map(async (member) => {
if (isMod(member)) {
connection.query(`SELECT * from users WHERE userID='${member.id}'`, (err, data) => {
if (data[0]) {
if (!data[0].warnedForInactivity && moment().isSameOrAfter(moment(data[0].lastMSGDate).add('2', 'week'))) {
count++;
var updateWarning = {warnedForInactivity: 1}
connection.query(`UPDATE users SET ? WHERE userID='${data[0].userID}'`, updateWarning);
member.send(`**[*]** WARNING: You've been inactive on \`\`${mainGuild}\`\` for 2 weeks. Members that have been inactive for at least a month will be kicked.`);
inactiveMembers += `${count}. ${member.user.tag}\n`;
return inactiveMembers;
}
}
});
}
});
await Promise.all(keyPromises).then(inactiveMembersData => console.log(inactiveMembers)); // RETURNS AN EMPTY STRING
setTimeout(() => console.log(inactiveMembers), 5000); // RETURNS THE INACTIVE MEMBERS AFTER WAITING FOR 5 SECONDS (PRMITIVE WAY)
}
inactiveMemberWarner();
先感谢您!
你很近,但不完全在那里。
首先,一些注意事项:
await
可以用于任何值,但将它用于任何不是 Promise 的值是完全没有意义的。 你的guildMembers.map(...);
返回一个数组,而不是 Promise。await
和.then(...)
有效,但有点混乱。 您已经在使用await
- 为什么还要处理回调?guildMembers.map(async...)
将确保所有请求或多或少立即被触发,并且它们可以以任何顺序完成。 这很好,但它是一种竞争条件,会导致或多或少随机的结果顺序。 您当前的代码不起作用的原因是您的connection.query
function逃脱了异步控制流。 我的意思是,使用 async/await 和 Promises 的全部目的基本上是在本地跟踪回调,并利用 promise 链接来动态添加回调。 如果您调用异步 function 并返回 Promise,您现在可以在代码中的任何其他位置携带该await
并动态附加成功处理程序.then()
。
But the connection.query
function doesn't return a Promise, it just has you pass another naked callback - this one is not being tracked by a Promise, The Promise doesn't have a reference to that callback, it can't know when该回调被调用。 因此,您的 async/await 控制流被转义,并且您的承诺在查询运行之前很久就解决了。
您可以通过在异步 function 中创建新的 Promise 来解决此问题:
async function inactiveMemberWarner() {
var msg = "```javascript\nI have sent warnings to members that have been inactive for 2 weeks.\n\n"
var inactiveMembers = '';
var count = 0;
var guildMembers = client.guilds.find(g => g.name === mainGuild).members;
const keyPromises = guildMembers.map(async (member) => {
if (isMod(member)) {
return new Promise((resolve, reject) => {
connection.query(`SELECT * from users WHERE userID='${member.id}'`, (err, data) => {
if (err) reject(err); //make errors bubble up so they can be handled
if (data[0]) {
if (!data[0].warnedForInactivity && moment().isSameOrAfter(moment(data[0].lastMSGDate).add('2', 'week'))) {
count++;
var updateWarning = {warnedForInactivity: 1}
connection.query(`UPDATE users SET ? WHERE userID='${data[0].userID}'`, updateWarning);
member.send(`**[*]** WARNING: You've been inactive on \`\`${mainGuild}\`\` for 2 weeks. Members that have been inactive for at least a month will be kicked.`);
resolve(`${count}. ${member.user.tag}\n`;);
}
} else resolve(""); //make sure to always resolve or the promise may hang
});
});
}
});
let inactiveMembersData = await Promise.all(keyPromises); // Returns an array of inactive member snippets.
inactiveMembers = inactiveMembersData.join(""); //join array of snippets into one string
}
inactiveMemberWarner();
这会起作用,但是有一个更好的方法。 SQL 支持IN运算符,它允许您拥有WHERE userID IN (list_of_ids)
等条件。 换句话说,您可以在一个查询中执行此操作。 您甚至可以指定更多条件,例如warnedForInactivity = 0
和lastMSGDate BETWEEN (NOW() - INTERVAL 14 DAY) AND NOW()
。 通过这种方式,您可以将所有当前处理逻辑卸载到 SQL 服务器上——您几乎每次都应该尝试这样做。 它也会大大简化这段代码。 我不会再做 go 了,因为这个问题已经超出了 scope 的范围,但如果你想不明白,请随时问另一个。
我无法对此进行测试,但这通常对我有用的是当想要等待 smt 时:
async function inactiveMemberWarner() {
new Promise(function(cb,rj){
var msg = "```javascript\nI have sent warnings to members that have been inactive for 2 weeks.\n\n"
var inactiveMembers = '';
var count = 0;
var guildMembers = client.guilds.find(g => g.name === mainGuild).members;
const keyPromises = await guildMembers.map(async (member) => {
if (isMod(member)) {
connection.query(`SELECT * from users WHERE userID='${member.id}'`, (err, data) => {
if (data[0]) {
if (!data[0].warnedForInactivity && moment().isSameOrAfter(moment(data[0].lastMSGDate).add('2', 'week'))) {
count++;
var updateWarning = {warnedForInactivity: 1}
connection.query(`UPDATE users SET ? WHERE userID='${data[0].userID}'`, updateWarning);
member.send(`**[*]** WARNING: You've been inactive on \`\`${mainGuild}\`\` for 2 weeks. Members that have been inactive for at least a month will be kicked.`);
inactiveMembers += `${count}. ${member.user.tag}\n`;
cb(inactiveMembers);
}
}
});
}
});
cb('No Members');
}).then(inactiveMembersData => console.log(inactiveMembers)); // SHOULD RETURNS THE INACTIVE MEMBERS
}
inactiveMemberWarner();
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.