2017-02-01 56 views
1

我正在爲網絡使用socketio創建Unity3D的nodejs服務器。我有一個作爲比賽室的功能,當球員離開比賽時我想離開這個功能。每次玩家創建一個新房間時,都應該輸入該功能並重新開始。是否有可能從子回調中中斷父函數的執行?從內部回調中斷父執行功能

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 
} 

編輯:忘了提及該功能正在導出。不知道這是否會改變任何事情。

編輯2:鑑於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; 
}); 

內部現在讓我們想象一下兩名球員,PLAYER1和player2在會議室1播放。玩家2退出服務器放棄遊戲。玩家1仍然連接,但必須離開當前的遊戲。所有變量都被刪除(如前所述),player1加入room2中的新遊戲。當player1嘗試移動時,將會調用2個回調函數:第一個initGame中添加的回調函數爲room = "room1",另一個執行第二個匹配項後添加:room = "room2"。拋出異常是因爲玩家沒有輸入key = room1

鑑於此,解決方案是從之前的比賽中獲得remove the listeners

+0

方式堆棧溢出被設計用於工作,您不應該根據提供的答案繼續使用漸進式發現來編輯問題。這是一個問答網站。您提出了一個問題(可以隨時編輯以澄清),我們提供了一個答案。當你從答案中獲得信息時,你不會繼續發展這個問題。這不是一個線程討論網站,我們將討論您正在發展的問題。你問一個明確的問題,我們爲這個問題提供了一個答案。你問的問題不應該改變。你可以澄清原來的問題。 – jfriend00

+0

如果在回答您的原始問題後,您還有其他問題出現在您學到的東西之後,那麼您會另外提出另一個問題。 – jfriend00

+0

此外,試圖描述代碼如何工作的所有文本對於讀者來說太複雜了。只需顯示實際的代碼(幾行代碼值得一百行文本),然後在文本中描述這個代碼的目標(您要完成的內容)。 – jfriend00

回答

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); 
     } 
    }); 
} 

這是一種簡單的回調之間的消息傳遞的 - 注意到第二個回調有權訪問是在第一個回調設置一些狀態。但是第一個回調中的代碼「控制」第二個回調是沒有意義的,除非第二個回調根據第一個回調中設置的狀態作出決定。

+0

謝謝您的解釋!這讓我對這個問題更加清楚。 –

2

不能。您不能停止執行子功能中的父功能。您可以從子函數中創建一個返回值,它將指示父函數接下來要執行的操作,然後父函數可以根據返回值管理自己。

但是,在你的例子中,initGame()很長時間以來,因爲在調用socket.on('something, ...)時執行完畢,所以你的整個問題只是一種錯誤。實際上,只有在initGame()已完成之後,您的事件處理程序才能被調用。 JS是單線程的,因此initGame()必須在調用任何事件處理程序之前完成執行。

此事件的順序如下:

  1. initGame()運行。
  2. 它在運行時,它會設置事件處理程序來偵聽各種套接字消息。這些是事件處理程序,用於響應將來發生的事件。
  3. initGame()然後結束執行。
  4. 然後,在將來的某個時間,會發生一個事件並且您的一個事件處理程序運行。沒有initGame()運行甚至試圖破壞執行。

如果您想要更具體的幫助,您需要在socket.on('something', ...)事件處理程序中顯示您實際嘗試完成的內容。從內部事件處理程序中「中斷父函數的執行」的整個概念在Javascript中甚至沒有意義。這種情況永遠不會發生在Javascript中。在事件處理程序可以調用之前,父函數已經執行完畢。您將不得不顯示您正在嘗試解決的實際問題,以便我們更詳細地幫助您。這似乎稍微麻煩這裏

的一件事是你引用socket,但沒有傳遞到initGame(),但要導出initGame(),並從其他一些方面調用它,所以它是不清楚怎麼socket變量可能可能是正確的變量。

+1

@YuriAlmeida - 我已經解釋了你目前的情況給出了你所展示的代碼(甚至在我的答案中增加了一些)。您將不得不從事件處理程序中顯示您實際嘗試完成的內容,以便我們進一步提供幫助。目前您尚未以任何方式描述真正的問題或顯示與實際問題相關的代碼。僅供參考,我認爲我已經回答了你剛纔提出的問題 - 不,你不能做你所要求的,因爲該功能已經完成執行。 – jfriend00

+0

哦,好吧,明白了!讓我詳細說明發生了什麼:玩家連接和遊戲在'initGame()'內存儲一個本地字符串'room'。添加了幾個回調,它使用局部變量'room'來訪問全局數組上的索引。玩家離開遊戲並加入另一個遊戲。當他加入第二個遊戲時,第一個和第二個遊戲的回調都被調用(並且拋出錯誤,因爲在全局arry中沒有更多的索引,因爲我在玩家離開遊戲時刪除了它們)。由於'initGame()'不再執行,我必須刪除回調?如果是這樣,怎麼辦? –

+1

@YuriAlmeida - 您在評論中描述的必須聽起來很複雜,似乎沒有顯示在您添加到問題中的代碼中(看不到您所談論的回調)。我建議如果你有狀態你想要存儲給定的用戶,你只需將自己的屬性添加到該用戶的'socket'對象並將其存儲在那裏。因爲狀態直接與它所屬的套接字關聯,所以它比你所做的要乾淨得多。您目前的方案實際上適用於您顯示的代碼,因爲它會創建持久的函數閉包,但不是最乾淨的。 – jfriend00