变量未正确更新

时间:2015-04-26 10:14:31

标签: javascript node.js global-variables

这是相关代码:

这会向服务器发送请求,将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.
        }

以上两个函数的工作原理是什么,没有什么可以改变/修复它。

现在我有一个函数接收来自一个用户的请求并向另一个用户发送请求,它需要2个参数:第一个arg是发送请求的用户的userId,第二个是用户的userName请求将被发送到服务器/游戏只适用于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 == undefined,除非我再次调用cmd.invite()然后idResult =='与之前的响应如下:

cmd.invite(user1);
cmd.invite(user2);
cmd.invite(user3);

idResult的输出是:

idResult == undefined
idResult == 'info for user1'
idResult == 'info for user2'

我尝试在响应处理程序之外定义idResult并在里面更新它,以确保它不是来自服务器的某种延迟我只是做了大量的垃圾邮件而且结果是相同的,无论我发送多快,都落后一步邀请。欢迎任何建议:)

2 个答案:

答案 0 :(得分:1)

问题很难解决,因为发送和收集回复是孤立的。似乎send()发送数据包并且handle()收到回复,并且在发送和接收之间可能存在许多可能不相关的数据包。

如果是这种情况,则应创建一个特殊的全局地图来链接请求和响应。对于同一个用户名有2个并发请求的情况,来自EventEmitter模块的events非常合适,因为它本质上是回调字符串的多重映射:

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的{​​{1}}回调电话:

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的需要实际上是一个实现细节,如果你想在代码中的多个位置查找userIds,它应该被正确封装/隐藏。

我将使用来自q npm库的promises,因为我记得接口,但类似的ES6承诺应该在生产代码中使用,因为它们是现代标准。

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

答案 1 :(得分:0)

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

所以你应该把send_PRIVGRP_INVITE(idResult)的调用放到send_CLIENT_LOOKUP(userName)

的回调或响应处理程序中