如何使函数在执行之前先等待其他函数完成

时间:2020-09-21 21:00:03

标签: javascript asynchronous discord discord.js

我一直在引用this线程的第一个和第二个答案,以尝试将异步函数引入我的程序。我正在尝试收集用户输入,然后再构建嵌入,然后将其发送回我的不和谐服务器。我尝试了几种不同的方法,但是没有取得任何进展。这是我现在所拥有的:

///// Lets start here
    execute(message, args) 
    {
        embedBuilder(message);
    },
};

// Collector to collect the users input and return it to some variable
async function collector(message,limit) 
{
    message.channel.awaitMessages(response => response.author.id === message.author.id, 
        {
            max: 1,
            time: 10000,
            errors:['time'],
        })
        .then((collected) => {
            if (collected.first().content.length < limit)
            {
                message.author.send(`I collected the message : ${collected.first().content}`);
                return collected.first().content;
            }
            //else
            collector(limit);
        })
        .catch(() => {
            message.author.send("No message collected after 10 seconds.")
        })
}

async function embedBuilder(message)
{
    message.author.send("Lets get to work!\nPlease enter the title of your event. (Must be shorter than 200 characters)");
    const title = await collector(message,200); // AWAIT HERE
    message.author.send("Please enter a short description of your event. (Must be shorter than 2000 characters)");
    const description = await collector(message,2000); // AWAIT HERE
    const eventEmbed = new Discord.MessageEmbed()
    .setColor('RANDOM')
    .setTitle(title)
    .setAuthor(message.author.username)
    .setDescription(description)
    .setImage();
    message.channel.send(eventEmbed);
}

现在它根本就没有等待,将我的两个提示都犁给用户,然后一次运行2个收集器,所以当我键入内容时,两个收集器都会返回相同的内容。

例如:

Me : !plan //Prompting the discord command
Bot: Lets get to work!
     Please enter the title of your event. (Must be shorter than 200 characters)
     Please enter a short description of your event. (Must be shorter than 2000 characters)
Me : Testing
Bot: I collected the message : testing
     I collected the message : testing

谁能指出我做错了什么?我相信我可能对JS中异步函数的工作方式有误解,但是我觉得我是根据链接文章中给出的答案遵循正确语法的。

感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

您需要返回您的承诺

async function collector(message,limit) 
{
    return message.channel....
            //else
            return collector(limit);

答案 1 :(得分:0)

实际上,您的问题与javascript中的异步编程有关,要实现此问题,您首先需要了解实现它们的方式

您可以通过多种方式来实现等待功能,以在该功能完成后执行一些代码:

  • 使用回调 通过这种方式,您可以创建一个函数,其中包含要在完成另一个代码之后执行的代码

示例:

const func =(...args,cb) => {
  console.log('execute this code first')
  console.log(4 * 4);
}
const callback = () => {
  console.log("call this after finishing the previous code")
}
  • 第二件事是在javascript中使用新的异步代码(称为promises),这个承诺非常简单,您可以在非阻塞代码中运行一些代码,并在代码成功或失败的情况下调用另一个函数。失败

这可以通过两种方式应用:

1-然后捕获

const successCb = () => {
 console.log("success");
}
const failCb = (err) => {
 console.log("failed", err)
}
message.channel.awaitMessages().then(successCb).catch(failCb)

2-第二种方法是使用异步/等待方式获得更简洁的代码

async function myFunc() {
  try {
     await message.channel.awaitMessages();
     console.log("process finished, continue execution")
  } catch(err) {
    console.log("failed")
  }
}

在您的问题中,首先需要指定应先执行什么代码,然后再执行代码,因此我们有两种方法:

  • 收集器(称为第一个)
  • 嵌入式构建器(稍后执行)

收集器(无效方式)

async function collector(message,limit) 
{
    message.channel.awaitMessages(response => response.author.id === message.author.id, 
        {
            max: 1,
            time: 10000,
            errors:['time'],
        })
        .then((collected) => {
            if (collected.first().content.length < limit)
            {
                message.author.send(`I collected the message : ${collected.first().content}`);
                return collected.first().content;
            }
            //else
            collector(limit);
        })
        .catch(() => {
            message.author.send("No message collected after 10 seconds.")
        })
}

您在这里有一些冲突,因为您定义了父函数将以异步方式工作,因此您需要在此方法内返回一个promise或在其中使用await来让该函数执行的解释器在其中执行promise,但是您没有不这样做,您会使用诺言。然后在异步函数中,当您在embedBuilder函数中使用它时,您将等待此父函数但不等待实际的诺言,因此,在执行另一个代码的同时执行诺言

收集器(有效方式)

您有两种选择,要么返回promise,要么在函数内部使用await,如下所示:

async function collector(message,limit) {
   try {
     let collected = await message.channel.awaitMessages(response => response.author.id === message.author.id, 
        {
            max: 1,
            time: 10000,
            errors:['time'],
        })
        if (collected.first().content.length < limit)
            {
                message.author.send(`I collected the message : ${collected.first().content}`);
                return collected.first().content;
            }
            //else
            collector(limit);
   } catch(err) {
     message.author.send("No message collected after 10 seconds.")
   }
}

然后您可以像以前一样在构建器中调用