I know like with GetAsync when you wrap it around you do lots of things like
Check if the first paramater of Pcall is true and if it returned Data
But SetAsync it seems different
local S,E = pcall(function() DataStore:SetAsync(plr.UserId,Data) end)
and from what I know E always is nil unless something goes wrong unlike GetAsync where you do something with the data
So I was wondering what should you do when after wrapping around pcall
Should I repeat SetAsync or like just do nothing when it fails
Also I was wondering if S returned false then would E always return something thats not nil?
ALSO Another thing is that since Pcall runs things inside it
does that mean I don't need to put another SetAsync or do I have to put SetAsync
like I've seen people do this
local S,E = pcall(function() DataStore:SetAsync(plr.UserId,Data) end) if S then DataStore:SetAsync(plr.UserId,Data) end
and Usually when I did this my dataStore throttled so I guess its bad practice
also Answer il try accept ur answer in like the next 10 hours
Ok so, let's forget about the :SetAsync()
and :GetAsync()
example. Let's just think about pcall
and how it works. pcall
, which stands for protected call, makes it so if a function errors it will prevent it from showing the error message in the output, so it's great for making your script not stop working. And it retuns two things:
1. a boolean value, indicating wether the function successfully ran. if it returned true
, that means the function successfully ran without any errors, but if it returned false
, that means the function errored
2. it returns the error message, the error that was supposed to be printed in the output. if pcall returned true at first, this would be nil because it didn't error so there is no error, but if the function did error it would return the error message.
(of course the name of what the function returns doesn't matter, you called them S, E, while you can call them anything else, like success, error)
So for an example, lets say we have a function that changes the color of a part. Technically if the part that we tried to change its color doesn't exist it would error, but with wrapping this function with pcall it shouldn't error, we also have extra information of whether the function ran succesffully or it failed, and the error message.
local success, error = pcall(function() game.Workspace.Part.BrickColor = BrickColor.new("Really Red") --lets say game.Workspace.Part doesn't exist which means this would error end) if success == true then print("successfully ran") else print("Someting happened: " .. error) end --i hope you get this part
That's basically how pcall works, we use pcall with :SetAsync()
and :GetAsync()
because you set or retrieve saved data there might be a sudden error for some background reasons like http errors and connection problems. And for :SetAsync()
and :GetAsync()
there shouldn't really be a difference while using pcall, it's the same stuff: whether they failed or succesfully worked.
Now, your last question which is "does pcall re-run the function if it failed?", and the answer is no. So simply we have to do it by ourselves. We will keep on checking if the function failed or not, and each time it fails we would. This what's going on.
local function repeater() local s,e = pcall(function() wait() data:SetAsync(something) end) if s then print("Success") else wait(3) repeater() print("Saving failed, retrying") end end
You can see what's happening is, the function will continue calling itself which means it will keep on saving the data until it finally works. This is a good method to save data.
Also another little info that's kind of out context, this is called "recursion", it's basically when a function keeps on calling itself until it finds a reason to stop.