Подтвердить что ты не робот

Как принудительно завершить процесс 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 { };
    }
}

Единственное решение, которое я мог придумать, - это зарегистрировать таймер с большим интервалом, чтобы вызывать пустую функцию, просто чтобы сохранить занятость планировщика и избежать пустого цикла событий, чтобы процесс продолжался вечно.

Есть ли способ сделать это лучше, чем я? Т.е. поддерживать процесс без необходимости использовать этот тип "хака"?

4b9b3361

Ответ 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, и оно должно работать вечно.