NodeJS:process.nextTick vs Instant Callbacking

Pij*_*usn 14 callback node.js

我写了很多看起来像这样的模块:

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

注意:它是我实际代码的简化版本.

该回调要么在同一个执行中调用,要么在稍后的某个时间调用.这意味着模块的用户不确定首先运行哪个代码.

我的观察是这样的模块重新引入了多线程的一些问题,这些问题以前是由JavaScript引擎解决的.

问题:我应该使用process.nextTick或确保在模块外部调用回调是安全的吗?

lan*_*nzz 12

这完全取决于你在回调函数中做了什么.如果你需要确保回调时回调还没有被触发get,你将需要process.nextTick流程; 在很多情况下,你不关心回调何时触发,所以你不需要延迟它的执行.无法给出适用于所有情况的确定答案; 始终将回调推迟到下一个滴答应该是安全的,但这种方式的效率可能会低一些,所以这是一个权衡.

我能想到的唯一情况就是你需要在下一次打勾时推迟回调,如果你真的需要在调用之后get但在调用之前为它设置一些东西callback.这可能是一种罕见的情况,也可能表明需要改进实际控制流程; 你应该完全依赖于何时调用你的回调,因此它所使用的任何环境都应该在get被调用的点设置.

在基于事件的控制流中存在某些情况(与基于回调的情况相反),您可能需要推迟实际的事件触发.例如:

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;
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您需要推迟缓存值的情况下,EMIT,否则该事件将调用者之前发出doSomething不得不附加一个听众的机会.使用回调时,通常不会考虑这一点.

  • 任何时候都不涉及多线程.唯一的区别是执行顺序可能是`get>(get之后的代码)> callback`或`get> callback>(get之后的代码)`,但`get`之后的代码不应该依赖于之前运行或者在'get`的回调之后. (4认同)

Jon*_*Ong 8

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

如果您在内部进行回调,请选择适合的方式

如果您正在创建其他人使用的模块,则异步回调应该始终是异步的.