0

我正在使用 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

4 回答 4

3

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

于 2012-05-05T14:22:04.580 回答
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)可能有助于满足您的需求,但它们通常会进行重新编译或类似的事情:如果您想使用,您必须决定您对它的适应程度他们。

于 2012-05-05T14:35:11.907 回答
0

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

这并不意味着同步调用是不可能的。它们是,并且它与您如何信任 3rd 方插件有关。如果有人决定在他们的插件中编写一个阻塞的调用,那么您将受到该调用的支配,它甚至可能是内部的并且没有在他们的 API 中公开的东西。因此,它可以阻止您的整个应用程序。考虑一下如果 Redis 花费大量时间返回,然后再乘以可能访问同一例程的客户端数量,会发生什么情况。整个逻辑已经序列化,他们都在等待。

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

于 2012-05-05T15:12:58.783 回答
0

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

var state = {}

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

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

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

于 2012-05-05T18:54:31.867 回答