Prevent callback from being called after being called once

Hello,

I have a callback function :AfterSave from DataStore2 (API - DataStore2) that returns Enum.ProductPurchaseDecision.PurchaseGranted as part of a developer product handling script.

The problem is that the callback is called each time the data is autosaved even after the purchase has been already granted. Is there a way to stop this?

Thank you

Could be anything. A function header does not a function make. It’s the code in between and the calling method that is often the crux.

I don’t think there are errors or what do you mean. It works as expected (it’s called each time data is saved/autosaved), but I don’t want it to be called anymore after being called once.

I mean I cant see the callback code, or the method you use to prevent a re-entry into the callback code. All I know is the function is a callback.

Oh, sorry, here’s the code

local function incrementData(player, productType, value)
	local data = DataStore2(productType, player)
	
	if data:IsBackup() then
		return Enum.ProductPurchaseDecision.NotProcessedYet
	end
	
	data:Increment(value)
	
	local result
	
	data:AfterSave(function()		
		result = Enum.ProductPurchaseDecision.PurchaseGranted
	end)
	
	while result == nil do
		RunService.Heartbeat:Wait()
	end
	
	return result
end

I want that callback to be called only once, grant the product, and then no longer listen to it.

I’ve not used DataStore2 before so I am unsure of whether the method you are using is a good way to do this. The anonymous callback called during data:AfterSave is permanently hooked and so will always be called however the save takes place. Maybe you could tag the value as saved using a dictionary where value = true and save that rather than just the value, then you can check for the value being true before returning the Enum. Or use a connect/disconnect method that connects initially to data:AfterSave then after the first call you disconnect and it will no longer be called.

1 Like

You can edit the source code a tiny bit to suit your needs.

function DataStore:AfterSave(callback)
	table.insert(self.afterSave, callback)
end

Change the above to:

function DataStore:AfterSave(callback: () -> boolean): number
    local nextIndex = #self.afterSave + 1

    if self.afterSave[nextIndex] then 
        warn(`Overwriting a callback at index {nextIndex}`) 
    end

	self.afterSave[nextIndex] = callback

    return nextIndex
end

And then just do this in your code:

local assignedIndex = data:AfterSave(function()		
	result = Enum.ProductPurchaseDecision.PurchaseGranted

    data.afterSave[assignedIndex] = nil
end)

Oh also, in the following code, make sure you change the ipairs to pairs or just do generalized iteration.

for _, afterSave in ipairs(self.afterSave) do --Change to pairs(self.afterSave) or just self.afterSave
	local success, err = pcall(afterSave, save, self)

	if not success then
		warn("Error on AfterSave:", err)
	end
end
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.