Как принудительно завершить процесс Node.js от завершения?
TL; DR
Каков наилучший способ принудительно поддерживать выполнение процесса Node.js, то есть не допускать, чтобы его цикл обработки событий был пустым и, следовательно, предотвращал завершение процесса? Лучшее решение, которое я мог придумать, было таким:
const SOME_HUGE_INTERVAL = 1 << 30;
setInterval(() => {}, SOME_HUGE_INTERVAL);
Который будет поддерживать интервал, не вызывая слишком много помех, если вы сохраняете интервал достаточно долго.
Есть ли лучший способ сделать это?
Длинная версия вопроса
У меня есть скрипт Node.js, использующий Edge.js для регистрации функции обратного вызова, чтобы ее можно было вызывать из библиотеки DLL в .NET. Эта функция будет вызываться 1 раз в секунду, посылая простой порядковый номер, который должен быть напечатан на консоли.
Часть Edge.js в порядке, все работает. Моя единственная проблема заключается в том, что мой процесс Node.js выполняет свой сценарий, и после этого у него заканчиваются события для обработки. С пустым циклом событий он просто завершается, игнорируя тот факт, что он должен был продолжать работать, чтобы иметь возможность получать обратные вызовы из DLL.
Мой скрипт Node.js:
var
edge = require('edge');
var foo = edge.func({
assemblyFile: 'cs.dll',
typeName: 'cs.MyClass',
methodName: 'Foo'
});
// The callback function that will be called from C# code:
function callback(sequence) {
console.info('Sequence:', sequence);
}
// Register for a callback:
foo({ callback: callback }, true);
// My hack to keep the process alive:
setInterval(function() {}, 60000);
Мой код С# (DLL):
public class MyClass
{
Func<object, Task<object>> Callback;
void Bar()
{
int sequence = 1;
while (true)
{
Callback(sequence++);
Thread.Sleep(1000);
}
}
public async Task<object> Foo(dynamic input)
{
// Receives the callback function that will be used:
Callback = (Func<object, Task<object>>)input.callback;
// Starts a new thread that will call back periodically:
(new Thread(Bar)).Start();
return new object { };
}
}
Единственное решение, которое я мог придумать, - это зарегистрировать таймер с большим интервалом, чтобы вызывать пустую функцию, просто чтобы сохранить занятость планировщика и избежать пустого цикла событий, чтобы процесс продолжался вечно.
Есть ли способ сделать это лучше, чем я? Т.е. поддерживать процесс без необходимости использовать этот тип "хака"?
Ответы
Ответ 1
Хотя, похоже, нет правильного ответа на этот вопрос, пока у нас есть 3 возможных взлома, и я искренне считаю, что мой подход менее навязчив:
setInterval(() => {}, 1 << 30);
Это установит интервал, который будет срабатывать примерно раз в 12 дней.
Первоначально мой хак передавал Number.POSITIVE_INFINITY
как точку, поэтому таймер фактически никогда не срабатывал, но это поведение было недавно изменено, и теперь API не принимает ничего больше 2147483647 (то есть, 2 ** 31 - 1
). См. документы здесь и здесь.
Для справки, здесь приведены два других ответа:
Джо:
require('net').createServer().listen();
Создаст "фиктивного слушателя", как он это назвал. Небольшой недостаток в том, что мы бы выделили порт только для этого.
Иакова:
process.stdin.resume();
Или эквивалент:
process.stdin.on("data", () => {});
Переводит stdin
в "старый" режим, устаревшую функцию, которая все еще присутствует в Node.js для совместимости со сценариями, написанными до Node.js v0.10 (ссылка).
Ответ 2
Используйте "старый" режим "Потоки", чтобы прослушать стандартный ввод, который никогда не придет:
// Start reading from stdin so we don't exit.
process.stdin.resume();
Ответ 3
Я добавлю еще один хак в микс. Вот как это сделать с Promise
new Promise(_ => null)
Бросьте это внизу файла .js
, и оно должно работать вечно.