从内部回调

时间:2017-02-01 15:59:35

标签: javascript node.js socket.io ecmascript-6

我正在为Unity3D创建一个nodejs服务器,使用socketio进行网络连接。我有一个作为比赛室的功能,我想在玩家离开游戏时离开该功能。每次玩家创建一个新房间时,它应该进入该功能并重新开始。是否可以从子回调中断执行父函数?

exports.initGame = function (userdata) {
    //do prematch stuff with userdata and execute game logic on the callbaks

    socket.on("something", function (someNetdata)({
        // how do i stop parent function from here?
    });

    // more socket.on callbacks
}

编辑:忘了提到正在导出该功能。不知道是否有任何改变。

EDIT2:鉴于jfriend00回答中讨论的建议,我将对问题进行更广泛的解释。

目前的流程如下:

用户连接,我在Io"连接"上定义了一些功能。打回来。相关的是startMatchMaker(Io, socket, data)。 matchMaker为玩家创建一个空间(如果有可用的话,则加入一个)并继续执行前面提到的gameInit(io, socket, room, data)

gameInit(...)函数以空间为关键存储全局数组的相关数据,例如Players[room] = {/* player object */}。匹配是1比1,所以当一个玩家放弃游戏时,我会从阵列中删除条目,引用该房间:delete Players[room]。当玩家移动时,我在全局数组中更新其对象上的玩家位置。这是在gameInit(...)

内添加的回调中完成的
socket.on("move", function(data){
    //do movement logic and update player position, if it is valid. Omitting the rest of the code.
    Players[room].position = data.position;
});

现在让我们想象两个玩家,玩家1和玩家2在room1中玩。 Player2退出服务器放弃游戏。 Player1仍然连接,但必须离开当前的游戏。删除所有变量(如前所述),player1加入room2中的新游戏。当player1尝试移动时,将调用2个回调:第一个initGame中添加了room = "room1"的回调和另一个在执行第二个匹配时添加的回调:room = "room2"。抛出异常是因为玩家中没有key = room1的条目。

鉴于此,解决方案是前一场比赛的remove the listeners

2 个答案:

答案 0 :(得分:2)

没有。您无法在子功能中停止执行父功能。您可以从子函数创建一个返回值,该值将指示父函数下一步做什么,然后父函数可以根据返回值自行管理。

但是,在您的示例中,initGame()在调用socket.on('something, ...)时执行已久,所以您的整个问题都是错误的。事实上,在initGame()已经完成之前,您的事件处理程序无法被调用。 JS是单线程的,因此initGame()必须在调用任何事件处理程序之前完成执行。

此处的事件顺序如下:

  1. initGame()运行。
  2. 在运行时,它会设置事件处理程序以侦听各种套接字消息。这些是事件处理程序,用于响应将来某个时间发生的事件。
  3. initGame()然后完成执行。
  4. 然后,在将来的某个时间,会发生一个事件,并且您的某个事件处理程序会运行。没有initGame()甚至试图破坏执行。
  5. 如果您需要更具体的帮助,则需要在socket.on('something', ...)事件处理程序中显示您实际尝试完成的内容。 "打破父功能执行的整个概念"来自内部事件处理程序在Javascript中甚至没有意义。这种情况永远不会发生在Javascript中。在调用事件处理程序之前,父函数已经完成执行。您必须向我们展示您尝试解决的实际问题,以便我们更详细地为您提供帮助。

    这里看起来有点令人不安的一件事是你引用socket,但是没有传递给initGame(),但是你正在导出initGame()并从其他一些上下文调用它,所以它目前还不清楚socket变量如何成为正确的变量。

答案 1 :(得分:1)

你父母的观念"功能有点困惑。没有"父功能"在Javascript。

看看上面的例子,好像你想在socket.on回调函数中做一些影响该函数之外的代码的事情。这里要认识到的重要一点是它是一个回调函数 - 当套接字收到标识为something的消息时,它会调用回调函数。没有涉及父母/子女关系。

所以现在说得更清楚了,让我们考虑一下你的问题。你还没有准确地解释你在回调之外想做什么,所以你不清楚你想要停止什么功能。但这并不是非常重要 - 基本上,你正在尝试做的是在内部回调发生时回调信号 回调。有很多方法可以做到这一点,但一种基本技术是使用变量作为信号。

重要的是要注意 node.js应用程序(通常)是事件驱动的。这意味着您的代码几乎总是在回调中响应正在发生的事情 - 没有"主循环"等待事情发生。

所以你的代码看起来像这样:

exports.initGame = function (userdata) {
    // do prematch stuff with userdata and execute game logic on
    // the callbacks

    // set up a variable to signal when something important happens
    var importantSignal = null;

    socket.on("something", function (someNetdata)({
        // something important has happened! let the rest of the application know about it
        importantSignal = someNetdata.message;

        // do some other stuff related to the callback
    });

    // another socket event
    socket.on("another", function (someNetData) {
        // has something important happened?
        if (importantSignal) {
            console.log("I see that 'something' has already happened!");
            console.log("Message = " + importantSignal);
        }
    });
}

这是在回调之间传递的一种简单类型的消息 - 请注意第二个回调可以访问在第一个回调中设置的某个状态。但是,第一次回调中的代码无法控制"第二个回调,除非第二个回调根据第一个回调中设置的状态做出决定。