我正在构建Discord音乐机器人,并且需要使用此功能生成一个对象。问题在于该函数返回得太早并且该对象未完全构建。功能中的循环仅在退出功能后结束。
功能fetchVideoInfo()
在.then()
所承诺的承诺功能中执行传递的回调,如镜像所提供。但是我不能编辑它,因为它是模块的一部分。我认为这是一个问题,即使我等待fetchVideoInfo()
完成,它仍然会因为它的写法而继续进行,并在内部promise之后执行回调。病态的部分代码返回了实际的承诺并调用了回调函数。我试过的是让我的函数返回诺言,但是对于我认为相同的问题却没有奏效,函数在回调之前就必须等待。我还尝试了将回调函数包装到另一个函数中,然后在等待初始函数的同时传递它,但效果也不佳。
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
对象未经修改,即使在该对象之前有for-await-循环(这是ES2018的新语法)。它应该首先完成for-of循环,然后返回
答案 0 :(得分:0)
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;
}
答案 1 :(得分:0)
所以这里有一个答案,但是它在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
}