代码之家  ›  专栏  ›  技术社区  ›  Đumić Branislav

如何在异步函数返回之前完成等待循环

  •  0
  • Đumić Branislav  · 技术社区  · 6 年前

    我正在构建一个不协调的音乐机器人,我需要用这个函数生成一个对象。问题是函数返回得太早,而对象没有完全生成。函数中的循环仅在函数退出后结束。

    功能 fetchVideoInfo() 执行传入的回调 .then() 承诺的功能,如图像上所示。但是我不能编辑它,因为它是模块的一部分。我认为这是一个问题,即使是我等待的那些 获取视频信息() 要完成,它仍然会继续,因为它是如何写的,在内部承诺之后执行回调。我将提供返回实际承诺并调用回调函数的部分代码。我所尝试的是让我的函数返回承诺,但它并不能解决我认为是同一个问题的问题,函数在回调之前结束,我必须等待。我还尝试将回调函数包装在另一个函数中,然后在等待初始函数时传递它,但它也做得不好。

    https://imgur.com/HdFF8VJ 这是链接到该模块中返回值的图像(“YouTube信息”)。整个模块实际上是 获取视频信息() 功能

    async function generatePlayList(queue) {
      const date = new Date();
      let embed = new Discord.RichEmbed();
      embed
        .setTitle("Playlist")
        .setColor("#25473A")
        .setDescription("Music currently in playlist!")
        .setFooter("Time ")
        .setTimestamp(date);
      for await (let id of queue)
        fetchVideoInfo(id, (Null, info) => {
          const { duration, title, url } = info;
          const seconds = duration % 60;
          const minutes = Math.trunc(duration / 60);
          embed.addField(`[${title}](${url})`, `Duration ${minutes}:${seconds}`);
          console.log(embed.fields);
        });
    
      console.log(embed.fields);
      return embed;
    }
    

    现在的情况是函数首先返回结果 embed 对象未被修改,即使之前有等待循环(它是新的ES2018语法)。它应该首先完成for-of循环,然后返回

    2 回复  |  直到 6 年前
        1
  •  0
  •   Zunnurain Badar    6 年前

    await不适用于回调,您必须更改您的函数,不应返回回调,而是返回一个值并使用它,并在出错时抛出错误并捕获它。因为的运行是异步的,所以需要等待的是您的函数。

    async function generatePlayList(queue) {
      const date = new Date();
      let embed = new Discord.RichEmbed();
      embed
        .setTitle("Playlist")
        .setColor("#25473A")
        .setDescription("Music currently in playlist!")
        .setFooter("Time ")
        .setTimestamp(date);
      for(let id of queue)
       {
        try{
        const info = await fetchVideoInfo(id);
        const { duration, title, url } = info;
        const seconds = duration % 60;
        const minutes = Math.trunc(duration / 60);
        embed.addField(`[${title}](${url})`, `Duration ${minutes}:${seconds}`);
        console.log(embed.fields);
        }catch(err){
           console.log("Error occur in embed");
         }
        }
    
      console.log(embed.fields);
      return embed;
    }
    
        2
  •  0
  •   Đumić Branislav    6 年前

    所以这里有一个答案,但在3分钟内就被删除了,但我还是尝试了一下,结果成功了!所以我把它贴在这里希望它能有用!

    async function generatePlayList() {
      const queue = this.queue;
      const date = new Date();
      let embed = new Discord.RichEmbed();
      embed
        .setTitle("Playlist")
        .setColor("#25473A")
        .setDescription("Music currently in playlist!")
        .setAuthor(this.bot.user.name, this.bot.user.avatarURL)
        .setFooter("Time ")
        .setTimestamp(date);
    
      let promises = queue.map(id => {
        return new Promise((resolve, reject) => {
          fetchVideoInfo(id, (err, info) => {
            if (err) return reject(err);
            const { duration, title, url } = info;
            const seconds = duration % 60;
            const minutes = Math.trunc(duration / 60);
            const fieldTitle = `${title.replace(/ *\([^)]*\) */g, "")}`;
            embed.addField(fieldTitle, `Duration ${minutes}:${seconds}`);
            resolve(embed);
          });
        });
      });
    
      return Promise.all(promises).then(values => {
        return values[values.length - 1];
      });
    }
    

    我在这里做的是做一个数组 promises 含A Promise 对于每个字段,我必须添加到对象中。每个承诺都在回调函数内部解决 fetchVideoInfo ,因此必须完成回调才能解决问题。然后我就把承诺还给你。所有的,都解决了每一个问题。 许诺 数组 承诺 并返回数组 values . 自从上次解决 许诺 是我挑的最新的东西吗 values[values.length - 1] 然后返回。promise.all将返回从 then 回调函数。

    当我调用函数时,我这样调用它:

    generatePlayList(array).then((embed)=>{
        //Do whatever
    })
    

    或者像这样:

    async function stuf(){
       let embed = await generatePlayList(array);
       //Do whatever
    }