这是相关代码:
这将向服务器发送一个请求,并将userName作为参数。
function send_CLIENT_LOOKUP(userName)
{
send(
auth.AOCP.CLIENT_LOOKUP,
[ [ 'S', userName.toString() ]
]
)
}
这部分处理来自服务器的响应。
handle[auth.AOCP.CLIENT_LOOKUP] = function (data, u)
{
console.log('CLIENT_LOOKUP')
var userId = u.I()
var userName = u.S()
u.done()
console.log({ userId : userId, userName : userName }) // this works properly
var idResult = userId; // I can actually use the userID but I just assigned it to idResult to make the code easier to understand.
}
以上两个函数按照它们应该的方式工作,没有什么可更改/修复的。
现在我有一个函数,它从一个用户接收请求,并向另一个用户发送请求,它需要两个参数:第一个参数是发送请求的用户的userId,第二个参数是请求将发送到的用户的用户名。然而,服务器/游戏只使用userId,因此必须转换userName:
var commands = {
invite: function(userId, userName) {
send_CLIENT_LOOKUP(userName); // send a request to the server to find out the userId of the userName
send_PRIVGRP_INVITE(idResult);
}
}
问题是idResult==未定义,除非我再次调用cmd.invite(),然后用以前的响应idResult==',如下所示:
cmd.invite(user1);
cmd.invite(user2);
cmd.invite(user3);
idResult的输出为:
idResult == undefined
idResult == 'info for user1'
idResult == 'info for user2'
我尝试在响应处理程序外部定义idResult,并在内部更新它,以确保它不是来自服务器的某种延迟。我刚刚做了一个大规模的邀请垃圾邮件,结果是一样的,无论我发送邀请的速度有多快,都落后了一步。欢迎任何建议:)
这个问题很难解决,因为发送和收集回复是孤立的。似乎send()
发送了一个数据包,handle()
接收了一个回复,在发送和接收之间可能有许多不相关的数据包。
如果是这种情况,那么应该创建一个特殊的全局映射来链接请求和响应。对于同一用户名有两个并发请求的情况,来自events
模块的EventEmitter
非常适合,因为它本质上是回调的字符串的多映射:
var events = require('events')
var outstandingLookups = new events.EventEmitter()
因此,当您发送查找时,您注册了一个一次性侦听器,因此不需要手动清理:
var commands = {
invite: function(userName) {
outstandingLookups.once(userName, function (idResult)
{
send_PRIVGRP_INVITE(idResult);
})
// send a request to the server to find out the userId of the userName
send_CLIENT_LOOKUP(userName);
}
}
响应处理程序emit
方便地为您调用接收到的userName
:的所有期望userId
的回调
handle[auth.AOCP.CLIENT_LOOKUP] = function (data, u)
{
console.log('CLIENT_LOOKUP')
var userId = u.I()
var userName = u.S()
u.done()
console.log({ userId : userId, userName : userName }) // this works properly
// I can actually use the userID but I just assigned it to idResult
// to make the code easier to understand.
var idResult = userId;
// this is the only addition to original handler code
outstandingLookups.emit(userName, idResult)
}
使用outstandingLookups.once
实际上是一个实现细节,如果您想在代码中的多个位置查找userId,则应该正确地封装/隐藏它。
我记得接口的时候,我会使用q
npm库中的promise,但类似的ES6 promise应该在生产代码中使用,因为它们是现代标准。
var Q = require('q')
var commands = {
lookupUserName: function (userName)
{
var result = Q.defer()
outstandingLookups.once(userName, function (idResult)
{
result.resolve(idResult);
})
// send a request to the server to find out the userId of the userName
send_CLIENT_LOOKUP(userName);
return result.promise
},
invite: function(userName) {
commands.lookupUserName(userName).then(function (idResult)
{
send_PRIVGRP_INVITE(idResult);
})
}
}
commands.invite
的代码现在干净多了。
看起来您正在执行异步请求,但正在同步更新var idResult
。
因此,您应该将对send_PRIVGRP_INVITE(idResult)
的调用放入send_CLIENT_LOOKUP(userName)
的回调或响应处理程序中