如何避免纠缠通过多个Meteor进程多次触发更改

How to avoid obserseChanges firing more than once with multiple Meteor processes

本文关键字:进程 纠缠 何避免 Meteor      更新时间:2023-09-26

这是我遇到的一个场景,无法找到如何避免观察到多次触发更改的明确答案。

我有这样的代码,听玩家的命令,并触发一个事件来触发AI模拟移动:

// Client-side
Deps.autorun(function() {
    var query = Games.find({
        "playerOne": "PlayerOne",
        "playerTwo": "Computer"
    });
    var handle = query.observeChanges({
        changed: function (id, fields) {
            // AI makes a move
            if (fields.playerTurn == "ComputerTurn" && fields.lastplay)
            // lastplay is a timestamp after player has played a turn
                Meteor.call("playComputerTurn", id);
        }
    });
});
//Server-side
Meteor.methods({
    'playComputerTurn': function(id) {
        // long code to simulate a computer turn
     }
});

对于一个Meteor进程,事件只触发一次,但在运行多个进程时,如果一个进程已经触发了一次,我似乎没有让observeChanges忽略事件的选项。

EDIT为了更清楚,在服务器重新启动的情况下需要重新运行事件,并且在服务器繁重的计算过程中,播放器不应"停止"。

我是否需要用队列中的光纤来包装服务器端事件,或者我可能错过了一些简单的东西,有人能帮忙或建议吗?

附言:如果只是将observeChanges放在服务器端,则observe将只运行一次。

您可以采取多种方法。您可以使用更改playerTurnupdate回调来调用该方法。那你就根本不需要观察员了。

// client
Games.update(gameId, {$set: {playerTurn: "ComputerTurn"}}, function (err) {
  if (!err) {
    Meteor.call("playComputerTurn", gameId);
  }
});

或者,你可以在轮到玩家时调用的方法中执行所有操作。

// server
Meteor.methods({
  'playComputerTurn': function(gameId) {
    var game = Games.findOne(gameId, ...);
    // make sure this.id is the current player
    // make sure it's this player's turn
    // play turn, set playerTurn, lastplay, etc.
    // long code to simulate a computer turn
  }
});

还要注意,如果使用观察器,它不需要在autorun内部运行,除非选择器是被动的。