我想澄清一下 - 何时使用setImmediate进行节点回调是正确的。
我研究的示例/文章认为最好使用setImmediate来确保回调是异步的。最常见的示例是“"缓存”中可能存在值的情况。 e.g。
const getData = function(id,callback) {
const cacheValue = cache[id];
if (cacheValue) {
// DON'T DO THIS ...
return callback(null,cacheValue);
// DO THIS ...
return setImmediate(callback,null,cacheValue);
}
return queryDB(id,function(err,result){
if (err){
return callback(err);
}
return callback(null,result);
});
};
这里让人感到困惑。回调中错误处理的大多数节点示例似乎永远不会调用setImmediate。从我上面的例子中可以看出:
if (err) {
return callback(err);
}
而不是:
if (err) {
return setImmediate(callback,err);
}
我读了一些论据,说在这种情况下setImmediate不是必需的,确实会影响性能,为什么会这样?此示例与访问缓存的示例不同。
保持一致并始终使用setImmediate是否更好?在那种情况下,为什么不这样做:
const getData = function(id,callback) {
const cacheValue = cache[id];
if (cacheValue) {
return setImmediate(callback,null,cacheValue);
}
return queryDB(id,function(err,result){
if (err){
return setImmediate(callback,err);
}
return setImmediate(callback,null,result);
});
};
答案 0 :(得分:2)
快速回答
如果您正在同步调用回调(在返回主机功能之前),则应使用setImmediate()
。如果您异步调用回调函数(函数返回后),则不需要它,可以直接调用回调函数。
更长的答案
如果你有一个接受回调的接口,并且回调至少有时被异步调用(意味着你的函数返回后将来会有一些无限期的时间),那么总是异步调用它是一个好习惯,即使结果立刻就知道了。这样,您的函数调用者和回调用户将始终看到一致的异步接口。
正如您所知,一个经典的例子就是缓存结果。如果结果在缓存中,则立即知道结果。
没有Javascript-land法则必须始终异步调用回调。如果回调有时被同步调用并且有时被异步调用,则代码可能正常工作,但它更容易受到回调使用方式导致的错误的影响。如果总是异步调用回调,那么调用者不太可能通过他们如何使用回调来意外地创建错误。
以下情况:
if (err) {
return callback(err);
}
我的猜测是,它已经处于异步位置。例如:
function someFunction(someUrl, callback) {
request(someURL, function(response, body, err) {
// this is already inside an async response
if (err) {
callback(err);
} else {
callback(body);
}
});
}
我读了一些论据,说在这种情况下setImmediate不是必需的,确实会影响性能,为什么会这样?此示例与访问缓存的示例不同。
在这种情况下,if (err)
已经在代码的异步回调部分中,因此不需要额外的setImmediate()
。主机功能已经返回,因此在没有setImmediate()
的情况下调用回调已经是异步定时。无需额外setImmediate()
。
需要setImmediate()
的唯一时间是当你仍然在函数的同步体中并调用回调时,会在host函数返回之前调用它,从而使回调同步而不是异步。 / p>
<强>摘要强>
节点回调中何时需要setImmediate
所以,总结一下。当您在返回主机功能之前同步执行的代码中时,应使用setImmediate(callback)
。当您所在的代码已经在异步回调中并且主机函数已经返回时,您不需要使用setImmediate(callback)
。
仅供参考,这是在异步编程接口(而不是普通回调)中专门使用promises的一个原因,因为promises已经自动为您处理此问题。它们保证解析的promise的.then()
处理程序将始终异步调用,即使promise是同步解析的。