我正在为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。
答案 0 :(得分:2)
没有。您无法在子功能中停止执行父功能。您可以从子函数创建一个返回值,该值将指示父函数下一步做什么,然后父函数可以根据返回值自行管理。
但是,在您的示例中,initGame()
在调用socket.on('something, ...)
时执行已久,所以您的整个问题都是错误的。事实上,在initGame()
已经完成之前,您的事件处理程序无法被调用。 JS是单线程的,因此initGame()
必须在调用任何事件处理程序之前完成执行。
此处的事件顺序如下:
initGame()
运行。initGame()
然后完成执行。initGame()
甚至试图破坏执行。如果您需要更具体的帮助,则需要在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);
}
});
}
这是在回调之间传递的一种简单类型的消息 - 请注意第二个回调可以访问在第一个回调中设置的某个状态。但是,第一次回调中的代码无法控制"第二个回调,除非第二个回调根据第一个回调中设置的状态做出决定。