【问题标题】:Promises in a broker-client communication using 0MQ使用 0MQ 的代理-客户端通信中的 Promise
【发布时间】:2014-01-22 12:35:12
【问题描述】:

我正在尝试开发一个代理,作为使用 0MQ 的一些工作人员和客户端之间通信的代理。这个任务在没有 Promise 的情况下相对简单,但是由于我对 Promise 的使用缺乏经验,我无法理解如何在这个示例中实现 Promise。

经纪人代码:

//Broker that serves as proxy for workers and clients
var zmq = require('zmq');
var frontend = zmq.socket('router');
var backend = zmq.socket('router');
var Q = require('q');

frontend.bindSync('tcp://*:8001');
backend.bindSync('tcp://*:8002');

var frontendOn = Q.nbind(frontend.on, frontend);
var backendOn = Q.nbind(backend.on, backend);

var requestFrontend = frontendOn('message').then(function(){
console.log("Message received");
});
var requestBackend = backendOn('message').then(responseBackend);

...

客户端代码:

//Client program that communicates with broker

var zmq = require('zmq')
var requester = zmq.socket('req');
var Q = require('q');

var arguments = process.argv.splice(2);

//Connect with broker
requester.connect(arguments[0]); 

console.log("Connected successfully to broker");

//Send message to broker
requester.send(arguments[1]);   

console.log("Message sent to broker");

...

客户端连接到代理,发送消息,但消息没有被代理处理。关于我做错了什么的任何想法?任何帮助将不胜感激。

【问题讨论】:

    标签: javascript node.js zeromq promise broker


    【解决方案1】:

    我没有使用过 ZeroMQ 但from the docs 我认为on 似乎是一种事件订阅机制,而不是接受回调的 NodeJS 风格的异步操作。它可能会触发不止一次,对吧?

    如果是这样,你为什么要使用 Promise?对于这种特殊情况,它们似乎是错误的抽象。

    Promise 表示完成或失败一次的操作,而不是异步的值流。

    就算

    var requestFrontend = frontendOn('message').then(function(){
      console.log("Message received");
    });
    

    有效,它对您没有任何好处,因为 then 只会被调用一次。
    我想这不是你想要的。

    如果您正在寻找一种过滤、映射、合并或限制异步序列的方法,您可以查看RxJS,它正是这样做的(它还与 Promise 交互)。但是承诺不应该,也不能用来替代触发多次的事件。


    另一方面,如果消息确实只出现一次,我同意最好使用 promise 将其抽象掉。但是,nfbindnbind 在这里不起作用,因为它们需要 function(err, result) 样式的回调,而您有 function(result)

    以下是我建议您改用的:

    function promiseOneMessage(queue) {
      var deferred = Q.defer();
    
      queue.on('message', deferred.resolve);
      queue.on('error', deferred.reject);
    
      return deferred.promise;
    }
    
    var requestFrontend = promiseOneMessage(frontend)
      .then(function (message) {
        console.log("Message received", message);
      })
      .done();
    
    var requestBackend = promiseOneMessage(backend)
      .then(responseBackend)
      .done();
    

    【讨论】:

    • 因此Q.nbind(frontend.on, frontend); ?每个事件都是对其价值的承诺。
    • @Benjamin:你到底是什么意思? Promise 只能完成一次,但处理程序不会去任何地方,所以 zeromq 将尝试调用处理程序无济于事。当然,您可以在每条消息上创建一个承诺,但我认为这不是 OP 想要的。 此外,zeromq on 不是 NodeJS 风格的函数:它的回调签名是function(message) 而不是function(err, result)。因此,任何承诺都会失败。
    • 啊,如果 zeromq 的情况是这样,您可能想在回答中澄清这一点。谢谢。
    • 非常感谢您的澄清。关于message事件是否会触发不止一次,我来说说沟通过程。每个正在运行的客户端仅向代理发送 1 条消息。然后,代理将消息转发给工作人员,该工作人员将消息的修改版本发送回代理。但这次是后端。所以实际上该事件只为前端触发一次(来自客户端),另一次为后端触发(来自工作人员)。
    • @ashe:它不起作用,因为nbind 需要接受error 作为第一个参数,result 作为第二个参数的 NodeJS 样式回调。所以当on 执行回调时,它会将message 作为第一个参数传递。但是 nbind 认为第一个参数将是一个错误(NodeJS 样式),因此它将 promise 标记为 failed 并以message 为原因。这就是为什么 then 在您的示例中从不执行的原因,但我敢肯定,如果您将 catch 添加到它,这就是消息所在的位置。干杯!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-11
    • 2012-04-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多