变量更新不正确



这是相关代码:

这将向服务器发送一个请求,并将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,则应该正确地封装/隐藏它。

我记得接口的时候,我会使用qnpm库中的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)的回调或响应处理程序中

相关内容

  • 没有找到相关文章

最新更新