Javascript 节点回调中何时需要setImmediate

Javascript 节点回调中何时需要setImmediate,javascript,node.js,Javascript,Node.js,我想澄清一下-什么时候使用setImmediate进行节点回调是正确的 我研究过的示例/文章认为最好使用setImmediate来确保回调是异步的。最常见的例子是值可能存在于“缓存”中,例如 这就是让人困惑的地方。大多数错误处理回调的节点示例似乎从未调用setImmediate。根据我上面的例子: if (err) { return callback(err); } 而不是: if (err) { return setImmediate(callback,err); } 我读过一

我想澄清一下-什么时候使用setImmediate进行节点回调是正确的

我研究过的示例/文章认为最好使用setImmediate来确保回调是异步的。最常见的例子是值可能存在于“缓存”中,例如

这就是让人困惑的地方。大多数错误处理回调的节点示例似乎从未调用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);
    });
};

快速回答

如果是同步调用回调函数(在宿主函数返回之前),则应使用
setImmediate()
。如果异步调用回调(在函数返回后),则不需要它,可以直接调用回调

更长的答案

如果您有一个接受回调的接口,并且该回调至少有时是异步调用的(这意味着在函数返回后的某个不确定的时间),那么始终异步调用它是一种良好的做法,即使结果是立即知道的。这样,函数的调用方和回调的用户将始终看到一致的异步接口

如您所知,这方面的一个经典示例是缓存结果。如果结果在缓存中,则立即知道结果

Javascript中没有一条定律规定必须始终异步调用回调。如果回调有时以同步方式调用,有时以异步方式调用,则代码可以正常工作,但它更容易受到回调使用方式引起的错误的影响。如果回调始终是异步调用的,那么调用方不太可能通过使用回调的方式意外创建错误

在下列情况下:

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()
的时间是当您仍然在函数的同步体中,并且在那里调用回调将在宿主函数返回之前调用它,从而使回调同步而不是异步

摘要

节点回调中何时需要setImmediate

总而言之。在宿主函数返回之前同步执行的代码中插入时,应使用
setImmediate(callback)
。当您所处的代码已经在异步回调中并且主机函数已经返回时,您不需要使用
setImmediate(callback)


仅供参考,这是在异步编程接口中专门使用承诺(而不是普通回调)的一个原因,因为承诺已经自动为您处理了。它们保证解析的承诺上的
.then()
处理程序将始终异步调用,即使承诺是同步解析的。

感谢您的详细回复。顺便说一句,你提到承诺可以解决这个问题。由于node现在支持async/await,我假设这是我可以选择的另一个选项?@ClickAhead-是的,
async/await
只是使用承诺的另一种方式。无论是否使用它,您都将从接口返回承诺,而不是传入回调。
function someFunction(someUrl, callback) {
    request(someURL, function(response, body, err) {
        // this is already inside an async response
        if (err) {
            callback(err);
        } else {
            callback(body);
        }
    });
}