何时在节点回调

时间:2017-11-08 16:28:48

标签: javascript node.js

我想澄清一下 - 何时使用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);
    });
};

1 个答案:

答案 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是同步解析的。