Javascript - Node.js - 防止函数的多次执行

Posted

技术标签:

【中文标题】Javascript - Node.js - 防止函数的多次执行【英文标题】:Javascript - Node.js - Prevent multiple executions of a function 【发布时间】:2014-04-19 18:38:12 【问题描述】:

我正在使用 Socket.io 创建一个 rochambo 游戏。玩家将他们的赌注添加到等待列表中,节点在 mondogDB 会话中检查玩家是否有足够的钱这样做,然后在将赌注发送给其他玩家之前创建赌注。

我的代码有效,但如果我要求非常快速地创建多个投注,节点没有时间在下一个投注到达之前更新 mongoDB 中的玩家余额,尽管我的等待名单。所以玩家即使没有足够的钱也可以下注,我想避免这种情况。

我找不到防止这种情况发生的方法。当然可以使用回调或递归函数,但我没有设法让它工作。

对不起,我的英语很差,我是法国人:)

这是代码的简化版本:

socket.on('placerunpari', function (screenName, amount, sign) 
newBetWaitingList.push(
    screenName: screenName,
    amount: amount,
    sign: sign
);
for (var k in newBetWaitingList) 

    screenName = newBetWaitingList[k].screenName;
    amount = newBetWaitingList[k].amount;
    sign = newBetWaitingList[k].sign;

    playerModel.findOne(
        screenName: screenName
    ).exec(function (err, player) 
        if (player != null) 
            if (checkAmounts(amount) && (sign == "scissors" || sign == "rock" || sign == "paper")) 
                if (amount <= player.balance) 

                    //DB writing
                    var newBet = new betModel(
                        screenName: screenName,
                        amount: amount,
                        sign: sign
                    );
                    newBet.save(function (err, res) 
                        io.sockets.socket(connected[screenName]).emit('mybet', newBet.id, amount, sign);
                        socket.broadcast.emit('newbet', newBet.id, screenName, amount);
                        creatorUpdateBalance(screenName, -amount);
                    )
                 else 
                    io.sockets.socket(connected[screenName]).emit('showalert', 'You don\'t have enough money for this bet', 'red');
                
             else 
                console.log('Unauthorized access');
            
        
    );
    newBetWaitingList.shift();
);

【问题讨论】:

您可以将所有投注推入一个队列,然后在计时器(例如 100 毫秒)后处理该队列。因此,您始终可以存储新的赌注,并有时间按到达的顺序处理它们。 ***.com/questions/4700935/… 你可以试试Redis缓存和列表数据结构,用小定时器协调一切会更快。 当您的网站需要在多台机器上运行时,您打算如何处理? 您考虑过使用互斥锁吗?也许这会有所帮助:github.com/jupiter/node-synchronized async.queueconcurrency = 1 在这里可能会有所帮助。 【参考方案1】:

感谢您的回答和帮助,它有效:

   function CreateBet(task, callback) 

    screenName = newBetWaitingList[k].screenName;
    amount = newBetWaitingList[k].amount;
    sign = newBetWaitingList[k].sign;

    playerModel.findOne(
        screenName: screenName
    ).exec(function (err, player) 
        if (player != null) 
            if (checkAmounts(amount) && (sign == "scissors" || sign == "rock" || sign == "paper")) 
                if (amount <= player.balance) 

                    //DB writing
                    var newBet = new betModel(
                        screenName: screenName,
                        amount: amount,
                        sign: sign
                    );
                    newBet.save(function (err, res) 
                        io.sockets.socket(connected[screenName]).emit('mybet', newBet.id, amount, sign);
                        socket.broadcast.emit('newbet', newBet.id, screenName, amount);
                        creatorUpdateBalance(screenName, -amount, function () 
                            callback();
                        );
                    )
                 else 
                    io.sockets.socket(connected[screenName]).emit('showalert', 'You don\'t have enough money for this bet', 'red');
                    callback();
                
             else 
                console.log('Unauthorized access');
                callback();
            
        
    );


var newBetWaitingList = async.queue(CreateBet, 1);

socket.on('placerunpari', function (screenName, amount, sign) 
    newBetWaitingList.push(
        screenName: screenName,
        amount: amount,
        sign: sign
    );
);

【讨论】:

以上是关于Javascript - Node.js - 防止函数的多次执行的主要内容,如果未能解决你的问题,请参考以下文章

如何防止 Node.js 将套接字消息拆分成更小的块

今日分享Node 核心和 Node eventLoop

Node服务器对比Java服务器

如何防止 node.js 中的内存泄漏?

如何防止 Node.js 在等待回调时退出?

node.js 的繁琐模块是不是有任何防止 sql 注入的功能?