Почему я не могу отловить обещания discord.js в обратных вызовах событий? - PullRequest
1 голос
/ 12 мая 2019

Итак, я создаю дискотечного бота.Для простоты, вот небольшая часть очень , которая иллюстрирует мою проблему:

const Discord = require('discord.js');

const client = new Discord.Client();

client.on('ready', async () => {
  throw new Error('Omg');
});

async function start() {
  try {
    await client.login(process.env.DISCORD_BOT_TOKEN);
  } catch (err) {
    console.error('Caught the promise rejections');
  }
}

start();

Когда я запускаю этот код, я ожидаю, что результат будет Caught the promise rejections, и процесс должен впоследствиивыход.Однако, это не так.Вместо этого я получаю PromiseRejectionWarning, и процесс не завершается (для этого нужно нажать Ctrl-C).Сначала я подумал, что, возможно, ошибки в обратных вызовах не распространяются на код, который их вызывает, поэтому я сделал еще один чистый пример JS:

const client = {
  on(event, callback) {
    this.callback = callback;
  },

  async login(token) {
    while (true) {
      // I assume the login method calls the callback in D.js 
      // (where else could it be called?)
      await this.callback();
      await sleep(5000);
    }
  },
};

client.on('ready', async () => {
  throw new Error('Omg');
});

async function start() {
  try {
    await client.login(process.env.DISCORD_BOT_TOKEN);
  } catch (err) {
    console.error('Caught the promise rejections');
  }
}

start();

Однако в этом случае выходные данные точно соответствуют ожидаемым;Я вижу строку из улова, и процесс немедленно завершается.Без перехвата я получаю необработанные ошибки отклонения обещания и незавершенный процесс.

Итак, мой вопрос: почему я не могу отловить отклонения обещания в своих обратных вызовах событий (например, on('ready'))?

1 Ответ

1 голос
/ 12 мая 2019

Причина в том, что ваш второй код не в том, как работает генератор событий разногласий, как в Node.js, встроенном в EventEmiter.

Функция обратного вызова для события ready не выполняется с await, и к нему не подключен обработчик .catch, поэтому вы получаете UnhandledPromiseRejectionWarning.

При использовании async в обратном вызове EventEmitter вы должны обработать ошибку, есливы не получите предупреждение, потому что никакой другой код не обрабатывает его.

client.on('ready', async () => {
  try {
     throw new Error('Omg');
  } catch(e) {

  }
});

В вашем конкретном случае кажется, что вы хотите вызвать ошибку, если какое-либо условие выполнено на «готово»».Так что вместо этого вы должны заключить слушателя в Promise.

function discordReady(client) {
    return new Promise((resolve, reject) => {

        client.once('ready', async () => {
            reject(new Error('Omg'));

            // resolve..
        }); 
    })
}


async function start() {
  try {
    await Promise.all([
        discordReady(client),
        client.login(process.env.DISCORD_BOT_TOKEN),
    ]);
  } catch (err) {
    console.error('Caught the promise rejections');
  }
}

, который даст вам ожидаемое поведение

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...