变量未正确更新

Variable not updating properly

这是相关代码:

这向服务器发送请求,将用户名作为参数。

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.
        }

以上 2 个函数按预期工作,change/fix 没有。

现在我有一个函数可以接收一个用户的请求并向另一个用户发送请求,它有两个参数:第一个参数是发送请求的用户的用户 ID,第二个是用户的用户名请求将被发送至,但是 server/game 仅适用于 userIds,因此必须转换 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 并在内部更新它,以确保它不是来自服务器的某种延迟我只是做了一个大量的邀请垃圾邮件,结果是一样的,无论多快都落后了一步我发送了邀请。欢迎提出任何建议:)

看起来您正在执行异步请求,但同步更新 var idResult

因此您应该将对 send_PRIVGRP_INVITE(idResult) 的调用放入 send_CLIENT_LOOKUP(userName)

的回调或响应处理程序中

这个问题比较难解决,因为发送和收集回复是孤立的。好像是send()发送了一个包,handle()收到了一个回复,发送和接收之间可以有很多可能不相关的包。

如果是这种情况,那么应该为 link 请求和响应创建一个特殊的全局映射。对于同一用户名有 2 个并发请求的情况,来自 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 方便地为您调用所有期望 userId 接收到的 userName 的回调:

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,则应该 encapsulated/hidden 是正确的。

我将使用 q npm 库中的 promise,因为我记得界面,但类似的 ES6 promises 应该用于生产代码,因为它们是现代标准。

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 的代码现在更清晰了。