如何在Node.js中同步处理回调?

时间:2012-05-05 14:16:03

标签: node.js asynchronous redis

我正在使用Redis为我的内存存储模型生成ID。 Redis客户端需要回调INCR命令,这意味着代码看起来像

client.incr('foo', function(err, id) {
  ... continue on here
});

问题是,我已经编写了应用程序的其他部分,希望incr调用是同步的,只需返回ID,这样我就可以使用它了

var id = client.incr('foo');

我遇到这个问题的原因是,到目前为止,我只是在内存中使用简单的闭包计数器函数生成ID,比如

var counter = (function() {
  var count = 0;
  return function() {
    return ++count;
  }
})();

简化测试并简化一般设置。

这是否意味着我的应用程序存在设计缺陷,我需要重写它以期待生成ID的回调?或者有没有简单的方法来同步呼叫?

4 个答案:

答案 0 :(得分:3)

Node.js本质上是一个异步I / O库(带插件)。因此,根据定义,那里没有同步I / O,您应该重写您的应用程序。

答案 1 :(得分:2)

这有点痛苦,但你需要做的是将计数器生成后的逻辑包装到函数中,然后从Redis回调中调用它。如果您有这样的事情:

var id = get_synchronous_id();
processIdSomehow(id);

你需要做这样的事情。

var runIdLogic = function(id){
  processIdSomehow(id);
}

client.incr('foo', function(err, id) {
  runIdLogic(id);
});

您需要进行相应的错误检查,但类似的内容应该适合您。

Node有几个顺序编程层(例如TameJS)可能对你想要的东西有帮助,但那些通常会重新编译或类似的东西:你必须决定你有多舒服如果你想使用它们。

答案 2 :(得分:0)

@Sergio在他的回答中简短地说了这句话,但我想再写一些扩展答案。 node.js是一种异步设计。它在单个线程中运行,这意味着为了保持快速并处理许多并发操作,所有阻塞调用必须对其返回值进行回调以异步运行它们。

这并不意味着无法进行同步调用。他们是,并且它关注你如何信任第三方插件。如果有人决定在他们的插件中写一个阻止的调用,那么你就可以接受那个调用,它甚至可能是内部的,而不是在他们的API中公开。因此,它可以阻止您的整个应用程序。考虑如果Redis花费大量时间返回可能会发生什么,然后通过可能访问相同例程的客户端数量多次。整个逻辑已被序列化,他们都在等待。

在回答您的上一个问题时,您不应该努力采用阻止方法。它现在看起来似乎是一个简单的解决方案,但它首先与node.js的好处相反。如果您在同步设计工作流程中感觉更舒服,则可能需要考虑以这种方式设计的另一个框架(使用线程)。如果您想坚持使用node.js,请重写现有逻辑以符合回调样式。从我看到的代码示例中,它看起来像一个嵌套的函数集,因为回调使用回调等,直到它可以从递归堆栈返回。

答案 3 :(得分:0)

node.js中的应用程序状态通常作为对象传递。我会做的更接近:

var state = {}

client.incr('foo', function(err, id) {
  state.id = id;
  doSomethingWithId(state.id);
});

function doSomethingWithId(id) {
  // reuse state if necessary
}

这只是一种不同的做事方式。