After a long time of work, I am finally ready to release my ProfileService wrapper; but theres one thing that bothers me. The function I am going to share below seems (to me) very long and not clean at all. Could you please tell me how to fix it?
function DataStoreObject:LoadDataAsync(player: Player, reconcileData: boolean?, claimedHandler: (placeId: number, gameJobId: string) -> () | "ForceLoad" | "Cancel"?)
reconcileData = OptionalParam(reconcileData, true)
claimedHandler = OptionalParam(claimedHandler, "ForceLoad")
local PlayerDataObject = setmetatable({ }, {__index = PlayerDataObject})
local PlayerData = self.DataStore:LoadProfileAsync(string.format(Settings.KeyStringPattern, player.UserId), claimedHandler)
local Created = os.time()
self.SessionLockClaimed:Fire(player)
PlayerDataObject.LoadedAt = Created
PlayerDataObject.Name = self.Name :: string
PlayerDataObject.Player = player :: Player
PlayerDataObject.Loaded = false :: boolean
PlayerDataObject.KeyChanged = Signal.new() :: ScriptSignal
PlayerDataObject.KeyAdded = Signal.new() :: ScriptSignal
PlayerDataObject.KeyRemoved = Signal.new() :: ScriptSignal
PlayerDataObject.GlobalKeyAdded = Signal.new() :: ScriptSignal
task.defer(function()
if PlayerData then
PlayerData:AddUserId(player.UserId)
if reconcileData then
PlayerData:Reconcile()
end
PlayerData:ListenToRelease(function()
LoadedPlayers[self.Name][player] = nil
setmetatable(PlayerDataObject, nil)
table.clear(PlayerDataObject)
player:Kick(`Could not save data for user {player.UserId}; possible data corruption. Retry later.`)
end)
if player:IsDescendantOf(Players) then
LoadedPlayers[self.Name][player] = PlayerData
for _, globalKey in ipairs(PlayerData.GlobalUpdates:GetActiveUpdates()) do
PlayerData.GlobalUpdates:LockActiveUpdate(globalKey[1])
end
PlayerData.GlobalUpdates:ListenToNewActiveUpdate(function(id, data)
PlayerData.GlobalUpdates:LockActiveUpdate(id)
end)
PlayerData.GlobalUpdates:ListenToNewLockedUpdate(function(id, data)
PlayerDataObject.GlobalKeyAdded:Fire(data.key_type, data.sent_data)
PlayerData.GlobalUpdates:ClearLockedUpdate(id)
end)
PlayerDataObject.Loaded = true
else
PlayerData:Release()
end
else
player:Kick(`Could not load data for user {player.UserId}; retry later.`)
console.warn(`Could not load data for user {player.UserId}; retry later.`)
end
end)
repeat task.wait() until PlayerDataObject.Loaded
return PlayerDataObject
end
In the latter, I am using string interpolation. The main problem I have is all those pesky indexes and the not so neat code overall.
Your code is actually fairly neat and clean in my opinion. One thing though, instead of using repeat task.wait() you can just use the signal module you’re using instead of repeat task.wait()
Code:
function DataStoreObject:LoadDataAsync(player: Player, reconcileData: boolean?, claimedHandler: (placeId: number, gameJobId: string) -> () | "ForceLoad" | "Cancel"?)
reconcileData = OptionalParam(reconcileData, true)
claimedHandler = OptionalParam(claimedHandler, "ForceLoad")
local PlayerDataObject = setmetatable({ }, {__index = PlayerDataObject})
local PlayerData = self.DataStore:LoadProfileAsync(string.format(Settings.KeyStringPattern, player.UserId), claimedHandler)
local Created = os.time()
self.SessionLockClaimed:Fire(player)
PlayerDataObject.LoadedAt = Created
PlayerDataObject.Name = self.Name :: string
PlayerDataObject.Player = player :: Player
PlayerDataObject.Loaded = false :: boolean
PlayerDataObject.KeyChanged = Signal.new() :: ScriptSignal
PlayerDataObject.KeyAdded = Signal.new() :: ScriptSignal
PlayerDataObject.KeyRemoved = Signal.new() :: ScriptSignal
PlayerDataObject.GlobalKeyAdded = Signal.new() :: ScriptSignal
local loadedEvent = Signal.new()
task.defer(function()
if not PlayerData then
player:Kick(`Could not load data for user {player.UserId}; retry later.`)
console.warn(`Could not load data for user {player.UserId}; retry later.`)
return
end
PlayerData:AddUserId(player.UserId)
if reconcileData then
PlayerData:Reconcile()
end
PlayerData:ListenToRelease(function()
LoadedPlayers[self.Name][player] = nil
setmetatable(PlayerDataObject, nil)
table.clear(PlayerDataObject)
player:Kick(`Could not save data for user {player.UserId}; possible data corruption. Retry later.`)
end)
if not player:IsDescendantOf(Players) then
PlayerData:Release()
return
end
LoadedPlayers[self.Name][player] = PlayerData
for _, globalKey in ipairs(PlayerData.GlobalUpdates:GetActiveUpdates()) do
PlayerData.GlobalUpdates:LockActiveUpdate(globalKey[1])
end
PlayerData.GlobalUpdates:ListenToNewActiveUpdate(function(id, data)
PlayerData.GlobalUpdates:LockActiveUpdate(id)
end)
PlayerData.GlobalUpdates:ListenToNewLockedUpdate(function(id, data)
PlayerDataObject.GlobalKeyAdded:Fire(data.key_type, data.sent_data)
PlayerData.GlobalUpdates:ClearLockedUpdate(id)
end)
loadedEvent:Fire()
PlayerDataObject.Loaded = true
end)
loadedEvent:Wait()
return PlayerDataObject
end