NodeJS: process.nextTick vs Instant Callbacking - программирование

NodeJS: process.nextTick vs Instant Callbacking

Я пишу много модулей, которые выглядят так:

function get(index, callback) {
    if (cache[index] === null) {
        request(index, callback); // Queries database to get data.
    } else {
        callback(cache[index]);
    }
}

Примечание: это немного упрощенная версия моего фактического кода.

Этот обратный вызов либо вызывается в том же самом исполнении, либо через некоторое время. Это означает, что пользователи модуля не уверены, какой код запускается первым.

Мое замечание состоит в том, что такой модуль повторно задает некоторые проблемы многопоточности, которые ранее были решены с помощью механизма JavaScript.

Вопрос: следует ли использовать process.nextTick или убедиться, что он безопасен для вызова обратного вызова вне модуля?

4b9b3361

Ответ 1

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

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

В потоке управления на основе событий (в отличие от callback-based) есть ситуации, когда вам может потребоваться отсрочка фактического срабатывания. Например:

function doSomething() {
    var emitter = new EventEmitter();
    cached = findCachedResultSomehow();
    if (cached) {
        process.nextTick(function() {
            emitter.emit('done', cached);
        });
    } else {
        asyncGetResult(function(result) {
            emitter.emit('done', result);
        });
    }
    return emitter;
}

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

Ответ 2

http://blog.izs.me/post/59142742143/designing-apis-for-asynchrony

если вы делаете обратные вызовы внутренне, делайте то, что подходит

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