標籤:ipa response blog pair 主函數 param 執行 insert remove
我們的遊戲有這樣一種情景:用戶端中角色需要用到一些公會的資料,但伺服器不會在玩家(創角後)一進入到遊戲裡就推送給玩家,而是需要用戶端自己在需要的時候向伺服器請求公會的資料,之前的實現就是在請求訊息的時候加一個回呼函數,訊息一回來就執行回呼函數繼續後續的業務!但後面發現存在這樣的不足:
1.有時會用到好多個參數,這就需要每次都把一些無關的參數傳給訊息要求者,然後回調過來再把這些參數原封不動地傳回來,很繁瑣;
2.這樣的回調寫法感覺很不符合人類的順序思維習慣,有點亂;
回調的lua代碼寫法類似:
--@callbackFunc帶的參數可能有(self, p1, p2, ..., [最後還有allianceData, 這個是取到資料後分發時加上的])function AllianceProxy:requestAllianceData(callbackFunc) --handle send request msg --這裡使用一個uniqueKey往一個管理器中註冊儲存這個回調endfunction AllianceProxy:responseAllianceData(allianceData) --handle receive response msg --這雷根據上面uniqueKey分發訊息,執行回調, 調用類似:callbackFunc(self, p1, p2, ..., allianceData)end--請求公會資料的寫法就是這樣:function Role:handleAllianceData() local function _callbackFunc(self, p1, p2, allianceData) --使用的到allianceData處理相關的商務邏輯 end AllianceProxy:requestAllianceData(packing(_callbackFunc, self, p1, p2)) --packing返回的仍然是一個functionend
上述的參數self, p1, p2, ...等等完全就沒必要往requestAllianceData中丟過去的,但就是因為收到回調後需要用到,作為強迫症的我,覺得這種寫法很噁心,所以今天想到,這完全可以利用lua提供的協程機制來做這件事,大致思路的代碼如下:(註:下面這些代碼未經過編譯及測試,另外還未考慮協程恢複執行時若其主函數所在table被銷毀的情況, 後續會完善下面的代碼)
--建立並運行一個協程--@param mainFunc 協程主函數function global:createAndRunningCo(mainFunc) self:assertFmt(type(mainFunc) == ‘function‘, ‘func=%s is not function‘, tostring(mainFunc)) local co = coroutine.create(mainFunc) local isSuccess, errMsg = coroutine.resume(co, co) self:assertFmt(isSuccess, ‘one error happened in mainFunc:%s‘, errMsg)endfunction global:checkCoIsRunning(co) self:assertFmt(type(co) == ‘thread‘) local curCo = coroutine.running() self:assertFmt(co == curCo, ‘co[%s] is not running, current running coroutine is %s, please sure that co is running‘, co, curCo)endfunction global:yieldAndSaveCo(key, co) self:assertFmt(key ~= nil) self:checkCoIsRunning(co) if coT[key] == nil then coT[key] = {} end table.insert(coT[key], co) return coroutine.yield()endfunction global:resumeAndRemoveCo(key, ...) if coT[key] then for _, co in ipairs(coT[key]) do if coroutine.status(co) == ‘suspended‘ then local isSuccess, errMsg = coroutine.resume(co, ...) self:assertFmt(isSuccess, ‘one error happened in mainFunc:%s‘, errMsg) end end coT[key] = nil endend
local global = require(‘global‘)global:createAndRunningCo(function(co) local allianceData = Alliance:requestAllianceData(co) --do somethingend)function AllianceProxy:requestAllianceData(co) --send msg : request alliance Data return global:yieldAndSaveCo(‘allianceData‘, co)endfunction AllianceProxy:responseAllianceData(allianceData) --receive msg : response alliance data global:resumeAndRemoveCo(‘allianceData‘, allianceData)end
需要擷取公會資料的使用者就使用下面這樣的寫法則可:
global:createAndRunningCo(function(co) local allianceData = Alliance:requestAllianceData(co) --do somethingend)
然後在訊息收發那裡做好相應的處理就行了,這個寫法跟前面的對比,很明顯,我們順序的編寫相應的邏輯就行了,完全不需要像前面的說等回調過來後反過頭來再執行相應的邏輯
[網遊用戶端商務邏輯] unity下使用lua開發商務邏輯