需求背景
一個服務緩存玩家信息到對象里,通過對象的函數定時同步到數據庫中,如果玩家掉線 清空對象,但是后續步驟導致對象數據需要變更,對象不存在, 就不方便變更了,怎么處理?
方案思考
1.臨時新建對象
既然更新數據依賴對象,判斷對象不存在的時候,先新建對象,再使用對象操作。
2.延后處理
判斷對象不存在的時候,先記錄函數名和參數,等對象下次出現的時候,延后調用。
方案選擇
因為項目中使用的對象涉及到網絡,玩家掉線情況下,參數不全,無法新建對象,所以選延后處理的方案比較合適。
具體代碼
demo
- 先看一個demo
local myFunction2 = function(arg1, arg2, arg3)print(arg1, arg2, arg3)
endlocal myFunction = function(arg1, arg2, arg3)local t = {arg1, arg2, arg3}local args = table.pack(arg1, arg2, arg3)myFunction2(table.unpack(args))
endmyFunction("hello", 42, {a = 2, b = 3})
- 可以通過
table.pack
將參數保存到table里,要使用的時候,再table.unpack
使用。 - 序列化的話,可以用
cjson.encode
第一版
- 存
-- 導入 lua-cjson 庫
local cjson = require("cjson")-- 定義一個要序列化的函數
local myFunction = function(arg1, arg2, arg3)print(arg1, arg2, arg3)
end-- 定義函數的參數
local args = {1, "hello", {a = 2, b = 3}}-- 序列化函數和參數
local serializedData = cjson.encode({func = myFunction, args = args})-- 打印序列化后的數據
print(serializedData)
- 取
-- 導入 lua-cjson 庫
local cjson = require("cjson")-- 被序列化的數據
local serializedData = '{"func":null,"args":[1,"hello",{"a":2,"b":3}]}'-- 反序列化數據
local data = cjson.decode(serializedData)-- 獲取函數和參數
local myFunction = data.func
local args = data.args-- 執行函數
if type(myFunction) == "function" thenmyFunction(unpack(args)) -- 使用 unpack 將參數展開傳遞給函數
elseprint("Invalid function.")
end
序列化之后可以存入redis,我這里使用的是redis的list。
其他
- 實際使用過程中碰到一些問題,比如
cjson.encode
的時候報錯Cannot serialise table: excessively sparse array
,原因是實際業務的args過于復雜。
這個錯誤通常發生在你嘗試使用 cjson.encode 函數序列化一個 Lua 表時,而這個表包含了“過于稀疏”的數組部分。所謂“過于稀疏”是指數組中存在很多 nil 元素,而 cjson 在序列化時對這樣的數組處理有一些限制。
- 查了一些解決方案,最后使用的是
cjson.encode_sparse_array(true)
- 使用上面方案之后,unpack(args)又異常了。于是調整代碼。
local serializedData = cjson.encode({func = myFunction, args = {arg1, arg2, arg3})-- ... 此處省略中間過程local data = cjson.decode(serializedData)
if data.func and self[data.func] thenlocal args = data.args or {}self[data.func](self, args[1], args[2], args[3], args[4], args[5], args[6], args[7])end
end
- 因為是通用方案,所以參數支持到7位,一般lua函數參數一般不會有這么多,實在超了,只能再加了。