无法通过 DiscordJS 中的不同范围传递变量

Posted

技术标签:

【中文标题】无法通过 DiscordJS 中的不同范围传递变量【英文标题】:Cannot Pass Variables Through Different Scopes in DiscordJS 【发布时间】:2020-05-08 20:50:32 【问题描述】:

好吧,所以我的问题是,在第一组console.log(streamXXXX)s 中,其中 XXXX 是各种变量,当我读取它们的值时,它们都按应有的方式读取,而在第二组中,它们读取为未定义。这是范围问题吗?也许是异步问题?我尝试在每次发出 Web 请求时添加等待,但似乎没有任何效果,最有趣的部分之一是没有错误?

无论如何,下面列出了我的代码,以及使用我创建的示例机器人在 Repl 中对其进行测试的链接。下面是该程序运行所需的库列表。谢谢!

if (!message.member.voiceChannel) return message.channel.send(`You do realize you have to be in a voice channel to do that, right $message.author.username?`)

if (!message.member.voiceConnection) message.member.voiceChannel.join().then(async connection => 

    let streamURL = args.slice(1).join(" ")
    let streamTitle = "";
    let streamThumb = "";
    let streamAuth = "";
    let streamAuthThumb = "";

    if (streamURL.includes("https://www.youtube.com") || streamURL.includes("https://youtu.be/") && !streamURL.includes(' ')) 
        youtube.getVideo(streamURL)
            .then(async results => 
                let 
                    body
                 = await snekfetch.get(`https://www.googleapis.com/youtube/v3/channels?part=snippet&id=$results.channel.id&fields=items%2Fsnippet%2Fthumbnails&key=$ytapikey`).query(
                    limit: 800
                )

                streamTitle = results.title
                streamThumb = results.thumbnails.medium.url
                streamAuth = results.channel.title
                streamAuthThumb = body.items[0].snippet.thumbnails.medium.url

                console.log(streamURL)
                console.log(streamTitle)
                console.log(streamThumb)
                console.log(streamAuth)
                console.log(streamAuthThumb)
            )
            .catch(console.error)
     else if (!streamURL.includes("https://www.youtube.com") || !streamURL.includes("https://youtu.be/")) 
        youtube.searchVideos(streamURL)
            .then(async results => 
                let 
                    body
                 = await snekfetch.get(`https://www.googleapis.com/youtube/v3/channels?part=snippet&id=$results[0].channel.id&fields=items%2Fsnippet%2Fthumbnails&key=$ytapikey`).query(
                    limit: 800
                )

                streamURL = results[0].url
                streamTitle = results[0].title
                streamThumb = results[0].thumbnails.default.medium.url
                streamAuth = results[0].channel.title
                streamAuthThumb = body.items[0].snippet.thumbnails.medium.url
            ).catch(console.error)
     else 
        return message.reply("I can only play videos from YouTube (#NotSponsored).")
    

    console.log(streamURL)
    console.log(streamTitle)
    console.log(streamThumb)
    console.log(streamAuth)
    console.log(streamAuthThumb)

    const stream = ytdl(streamURL, 
        filter: 'audioonly'
    )
    const dispatcher = connection.playStream(stream)
    dispatcher.on("end", end => 
        return
    )

    let musicEmbed = new Discord.RichEmbed()
        .setAuthor(streamAuth, streamAuthThumb)
        .setTitle(`Now Playing: $streamTitle`)
        .setImage(streamThumb)
        .setColor(embedRed)
        .setFooter(`$streamAuth - $streamTitle ($streamURL`)

    await message.channel.send(musicEmbed)
)

Link to test out the program on a sample bot I made

您需要测试的模块:

discord.js
simple-youtube-api
node-opus
ffmpeg
ffbinaries
ffmpeg-binaries
opusscript
snekfetch
node-fetch
ytdl-core

再次感谢!

【问题讨论】:

在第一组streamTitle = results.title,在第二组streamTitle = results[0].title 你确定results是一个列表并且第二组第一项有url属性吗? 是的,文档说这样做是因为searchVideo() 返回多个结果,而getVideo() 只返回一个 【参考方案1】:

您的输出为 undefined 的原因是由于 Promise 的工作方式以及您如何构建代码:

let streamTitle = "";

// 1. Promise created
youtube.getVideo(streamURL)
  // 2. Promise still pending, skip for now
  .then(async results => 
    // 4. Promise fulfilled
    console.log(results.title); // 5. Logged actual title
);

console.log(streamTitle); // 3. Logged ""

您已经为您的snekfetch 请求提供了正确的方法,只需要将其应用到 YT 请求即可:

let streamTitle = "";

const results = await youtube.getVideo(streamURL);

streamTitle = results.title;

console.log(streamTitle); // Desired output

【讨论】:

好的,这解决了我最初的传递变量问题,非常感谢!我一直在思考这个问题很长一段时间,但无法找到一个可靠的答案。现在到我的下一个问题:我怎样才能播放一些音频?我在不同情况下测试的代码运行良好,但在这里它似乎什么也没做。 请使用您的音频问题的相关代码创建一个新问题。

以上是关于无法通过 DiscordJS 中的不同范围传递变量的主要内容,如果未能解决你的问题,请参考以下文章

通过 Javascript 中的变量范围维护变量

随机森林变量长度不同

函数/变量范围(通过值或引用传递?)

java是通过值传递,也就是通过拷贝传递——通过方法操作不同类型的变量加深理解

无法将变量从控制器传递到模型以处理codeigniter中的多个上载字段

Labview 局部变量