Как ожидать завершения цикла перед возвратом в асинхронную функцию - PullRequest
0 голосов
/ 23 января 2019

Я создаю музыкального бота Discord, и мне нужно сгенерировать один объект с помощью этой функции.Проблема в том, что функция возвращается слишком рано, и объект строится не полностью.Цикл в функции завершается только после выхода из функции.

Функция fetchVideoInfo() выполняет переданный обратный вызов в функции .then(), обещая, что он возвращается, как указано на изображении.Однако я не могу редактировать это, потому что это часть модуля.Проблема в том, что, несмотря на то, что я ожидаю завершения fetchVideoInfo(), он все еще продолжается из-за того, как он написан, выполняя обратный вызов после внутреннего обещания.Я предоставлю ту часть кода, которая возвращает фактическое обещание и вызывает функцию обратного вызова.Я попытался получить обещание возврата функции, но оно не сработало, потому что я думаю, что это та же проблема, функция завершается до обратного вызова, который я должен ждать.Я также попытался обернуть функцию обратного вызова в другую и затем передать ее, ожидая начальной функции, но это также не помогло.

https://imgur.com/HdFF8VJ Это ссылка на изображение возвратазначение в этом модуле ("youtube-info").Весь модуль на самом деле является fetchVideoInfo() функцией

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 объект остается неизменным, даже если есть цикл - await - (он новыйСинтаксис ES2018) перед этим.Сначала он должен завершить цикл for -, а затем вернуть

Ответы [ 2 ]

0 голосов
/ 23 января 2019

Итак, здесь был ответ, но он был удален в течение 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, содержащий Promise для каждого поля, которое я должен добавить кобъект.Каждое обещание разрешается внутри функции обратного вызова для fetchVideoInfo, поэтому оно должно завершить обратный вызов для разрешения.Затем я возвращаю Promise.all, который разрешает каждый Promise массив promises и возвращает массив values.Поскольку последний разрешенный Promise - это тот, который содержит последний объект, я выбираю его с помощью values[values.length - 1] и возвращаю.Promise.all вернет значение, которое возвращается из then функции обратного вызова.

И когда я вызываю функцию, я вызываю ее так:

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

Или вот так:

async function stuf(){
   let embed = await generatePlayList(array);
   //Do whatever
}
0 голосов
/ 23 января 2019

Await не работает с обратными вызовами, вы должны изменить свою функцию и не должны возвращать обратный вызов, вместо этого возвращайте значение и используйте его, а также в случае ошибки и перехвата.for работает асинхронно, так что ваша функция должна ждать.

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...