如何在socket.io上进行RPC?

6
假设我们有一个简单的回声服务器(在第一次请求时调整为较长时间):
var waiting = 8000;
io.on('connection', function(socket){   
    socket.on('doEcho', function (data) {
        setTimeout( function () {
            socket.emit('echoDone', data);
        }, waiting);
        waiting = 1;
    });
});

那么,一个名为 index.html 的客户端脚本会执行以下操作:
askEcho ("11111", function (resp) {
         console.log("answer for 11111 " + resp);
});
askEcho ("22222", function (resp) {
         console.log("answer for 22222 " + resp);
});

其中askEcho是以下有缺陷的函数,假装是一个RPC存根:
function askEcho (text, fun) {
     socket.emit('doEcho', text);
     socket.on('echoDone', function (data) {
         fun ( data );
     });
  }

显然,我得到的是以下混乱的内容:
答案为11111 22222 答案为22222 22222 答案为11111 11111 答案为22222 11111
因为我安装了两个相同事件的监听器。这可以很容易地解决,但我不清楚如何在客户端正确有序地获取响应,而无需在服务器端进行更多的编程帮助。
所有这些似乎都太过繁琐了。 难道不能正确轻松地编写askEcho函数吗?
2个回答

5

4
实际上,有一个简单的技巧:使用计数器来区分答案,并在完成后删除回调函数(最好使用once而不是on)。这只会对服务器和客户端产生轻微的变化。
让我们展示一下:
回显服务器是(现在没有任何延迟超时):
io.on('connection', function(socket){   
    socket.on('doEcho', function (callCounter, data) {    
        socket.emit('echoDone'+callCounter, data);
    });
});

在客户端(index.html)中,用户代码仍然是相同的,正如期望的那样:
askEcho ("11111", function (resp) {
    console.log("answer for 11111 " + resp);
});
askEcho ("22222", function (resp) {
    console.log("answer for 22222 " + resp);
});

以下是与服务器端良好协作的存根askEcho

var callCounter = 0;
function askEcho (text, fun) {
     var localCallCounter = ++callCounter;
     socket.emit('doEcho', localCallCounter, text);
     socket.once('echoDone'+localCallCounter, function (data) {
         // not required: socket.removeListener ('echoDone'+localCallCounter);
         fun ( data );
     });
 }

如果您懒得自己实现,我有一个小库:https://github.com/capaj/socket.io-rpc - Capaj
有时候回调函数永远不会被移除。处理它们(超时、断开连接时的清理等)很麻烦,所以我不认为这是一个简单的技巧。 - polkovnikov.ph

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接