Почему программа nodejs завершается при использовании await и EventEmitter?

Взгляните на этот код:

const { EventEmitter } = require('events');

class Trigger extends EventEmitter {
  constructor () {
    super();
  }

  run() {
    setTimeout(() => {
      this.emit('done');
    }, 1000);
  }

  waitUntilDone() {
    const this_ = this;
    return new Promise((resolve) => {
      this_.on('done', () => {
        resolve();
      });
    })
  }
}

async function main() {
  const tr = new Trigger();
  tr.run();
  console.info('run');
  // 如果监听的事件永远不会抛出,则此处程序会直接退出
  await tr.waitUntilDone().then(() => console.info('Promise done'));
  await tr.waitUntilDone().then(() => console.info('Promise done'));
  console.info('final done');
}

main();

Программа завершится на втором await tr.waitUntilDone().t... без регистрации.

Даже второй tr.waitUntilDone() никогда не получит событие, он должен ждать вечно, не так ли?

Имейте в виду, что node.js не дожидается выполнения обещаний перед завершением. Он действительно ждет таймеров (если вы их не .unref()). И помните, что main() немедленно возвращает обещание. Он не блокируется await.

jfriend00 15.01.2019 02:43

@ Саши, он рано уходит. Pingze, const this_ = this; не нужен, так как вы используете стрелочные функции.

Jared Smith 15.01.2019 02:43

Итак, я полагаю, что возможно, что node.js завершится между временем срабатывания второго таймера и до того, как будет вызван ваш второй обработчик .then(), таким образом пропуская запись в журнал final done.

jfriend00 15.01.2019 02:45
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
394
3

Ответы 3

Если вы сбросите таймер после разрешения первого обещания, программа не выйдет, пока не будет выполнено последнее обещание.

async function main() {
    const tr = new Trigger();
    tr.run();
    console.info('run');

    await tr.waitUntilDone().then(() => { 
        console.info('Promise done'); 
        // Reset the timer (this will keep the program alive)
        tr.run();
    });
    await tr.waitUntilDone().then(() => console.info('Promise done'));
    console.info('final done');
}

Вы увидите результат:

run
Promise done
Promise done
final done

Я думаю, вы должны использовать только одну вещь: Promise или Async / Await.

1] Пример Async / Await

async function main() {
    const tr = new Trigger();
    console.info('run');

    tr.run();
    await tr.waitUntilDone();
    console.info('Promise done');

    tr.run();
    await tr.waitUntilDone();
    console.info('Promise done')

    console.info('final done');
}

2] Пример обещания

function main() {
  const tr = new Trigger();
  console.info('run');
  tr.run();
  tr.waitUntilDone().then(() => console.info('Promise done'));
  tr.waitUntilDone().then(() => console.info('Promise done'));
  console.info('final done');
}

Ваше выражение "await tr.waitUntilDone().then(() => console.info('Promise done'));" неверно. Правильнее будет что-то вроде этого "await tr.waitUntilDone().then(() => (console.info('Promise done'), Promise.resolve()));" или "tr.waitUntilDone().then(() => console.info('Promise done'));"

Если вы хотите, чтобы ваша программа работала вечно, вы можете добавить это в начало своего кода:

(function keepalive() {
    setTimeout(keepalive, 0x7FFFFFFF);
})();

По сути, пока есть ожидающее событие, среда выполнения должна оставаться открытой. Надеюсь, это будет полезно.

Другие вопросы по теме