通过JavaScript中的Promise链编辑机器人的不和谐消息

时间:2019-11-03 19:15:44

标签: javascript node.js promise discord.js

我目前正在开发一款不和谐的机器人,我想实现的命令之一是使用edit命令编辑该机器人先前通过其发送的消息-我正在使用{{3}为此,从文档中看来,我似乎需要使用promise链来实现我想要的功能,但是我在一些小片段上有些困惑。我当前的代码如下:

module.exports = {
    name: 'edit',
    description: 'Edit one of the bot\'s messages',
    args: true, // does the command have arguments?
    guildOnly: true, // can this command be used outside of the discord channel?
    execute(message, args) {
        if (args.length < 2) {
            console.log("Insufficient arguments provided");
            return;
        }
        const server = message.guild;
        let id = args.shift();
        let newMessage = args.join(' ');

        let channels = server.channels;
        for (let [, channel] of channels) {
            if(channel.type === 'text') {
                channel.fetchMessage(id)
                .then(response => {
                    return response;
                }, _reason => {
                    console.log("still looking");
                })
                .then(function (message) {
                    message.edit(newMessage)
                    .then(editedMessage => {
                        console.log(`new message content: ${editedMessage}`);
                    })
                    .catch(console.error);
                })

            }
        }
    },
};

基本上,我的思考过程如下:可以在任何通道中使用该命令来编辑任何其他通道中的bot消息-为此,我需要循环浏览所有服务器通道并检查适当的消息ID(如上for循环所示)-这是我感到困惑的地方,fetchMessage命令(见discord.js)返回了一个promise,但是我主要担心的是,如果消息是不是,我希望该机器人继续查找直到找到它。一旦完成,我会尝试将另一个承诺链接到实际的here;这时,我会向不一致的人发送一条消息,指出该过程已成功完成-从现在开始,一旦检查了第一个通道并且没有找到消息,我的代码当前就会出错,这可能是由于{ {1}}块。我的问题是:如果程序在第一次尝试中未找到消息,如何使程序不出错呢?如果确实找到了正确的消息,我该如何保证正确地编辑它呢?

2 个答案:

答案 0 :(得分:0)

我建议您添加一个channel参数,但是如果您确实想按自己的方式做,则只需捕获fetchMessage()。另外,我不了解您第一个.then()的目的。这是我的处理方式:

if (args.length < 2) {
  console.log("Insufficient arguments provided");
  return;
}
const server = message.guild;
let id = args.shift();
let newMessage = args.join(" ");

let channels = server.channels;
for (let [, channel] of channels) {
  if (channel.type === "text") {
    channel
      .fetchMessage(id)
      .then(message => {
        message.edit(newMessage).then(editedMessage => {
          console.log(`new message content: ${editedMessage}`);
        });
      })
      .catch(e => console.log("Not this channel"););
  }
}

答案 1 :(得分:0)

假设它是一个数组(或可以转换为数组),message.guild.channels可以通过首先形成一个.catch()链进行异步扫描,该链在下面以基于Array.prototype.reduce()的模式构建。

module.exports = {
    'name': 'edit',
    'description': 'Edit one of the bot\'s messages',
    'args': true,
    'guildOnly': true,
    execute(message, args) {
        if (args.length < 2) {
            return Promise.reject(new RangeError('Insufficient arguments provided')); // ensure that execute() returns a Promise
        }
        let id = args.shift();
        let newMessage = args.join(' ');
        return message.guild.channels.reduce((rejetedPromise, [, channel]) => { // assuming `message.guild.channels` to be Array
            return rejetedPromise.catch(error => {
                if (channel.type === 'text') {
                    return channel.fetchMessage(id); // will resolve to `msg` if found and drop through to the then() below,
                                                     // otherwise will reject and flow will keep going to the next catch formed by the reduction.
                } else {
                    throw new Error('channel(s) searched but message not found'); // keep going to next catch
                }
            });
        }, Promise.reject('no channels')) // starter Promise for the reduction. If `message.guild.channels.length === 0`, this promise will fall straight through to the .catch() below
        .then(msg => msg.edit(newMessage)) // execution will arrive here only if a `channel.fetchMessage(id)` above succeeds.
        .then(editedMessage => { // this whole clause is optional.
            console.log(`new message content: ${editedMessage}`);
            return editedMessage; // return whatever is of interest to execute()'s caller.
        })
        .catch(error => { // this whole clause is optional.
            console.error(error);
            throw error; // rethrow error to inform execute()'s caller of the error.
        });
    }
};

message.guild.channels.reduce(...)块说明了一些问题。

它构造了一个捕获链,如果手动构建,则捕获链的形式为:

Promise.reject().catch(...).catch(...).catch(...).catch(...).then(...);

将其与更熟悉(且更易于理解)的链条进行比较:

Promise.resolve().then(...).then(...).then(...).catch(...);

捕捞链的本质是其解决:

  • 只要捕获或返回的Promise被/将被拒绝,它们就会从catch回调运行到catch回调。
  • 一旦任何catch回调返回将要解决的值或Promise,
  • 将跳到最后的.then()

因此,您将获得所需的东西-机器人可以继续在一个频道中查找,直到找到所需的消息为止。