Do you use pcalls?

Recently,
I’ve seen a post about a service which certinaly requires pcalls,
and the solutions I saw there, were totally bad practice which could cause issues to player’s game when the web is down. And it really bothers me, simply because it’s 2022 and people still use bad practice. Why is that? I really want to know why people dont want to use a better and safer method, I understand they’re used and think it’s easier, but no - using pcalls is even easier than you think.

Now, I accept the reasons:
1.Easier to use.
2.Used to it.
3.Looks ‘neater’.
etc…

But afterall, the reason pcalls are there is to help your game handle data and stuff incase the web is down. And my question is - why’d you want to avoid such a magnificent & powerful tool?

In the past, when I didnt know about pcalls, I later on saw errors occurring very often [ the data store and scripts were 100% correct, but apparently they were bad practice.] And since I got used to pcalls, I am still amazed and still use them in every script there is anything related to the web and could potentially fail due to issues.

So back then I used to do:

if game.BadgeService:UserHasBadgeAsync(UserId,BadgeId) then end
if game.MarketplaceService:UserOwnsGamePassAsync(UserId,GamepassId) then end
if data then end -- data isnt wrapped in a pcall here

And after long time, I finally learned that this is an atrocious practice which you should avoid using. And then I started using pcalls - and they are awesome!

Importance of pcalls:
What are pcalls - and how to use them
Why should I use pcalls?
Is it good to use pcalls? And When?

Why did I make this post?
1.To hopefully raise the awareness of how important pcalls are.[examples could be shown above, linked them].
2.To hear others opinions on this topic and to see how/if using pcalls have affected you so far.

Do you use pcalls?
  • Yes.
  • Nah.

0 voters

2 Likes

I use pcalls when I intentionally want the function to error.

Example:

for i,v in pairs(workspace:GetDescendants()) do
pcall(function()
if v.CanCollide or not v.CanCollide then – this would error occasionally for things like terrain & camera because that property doesn’t exist for them
print(v.Name … " is a mesh")
end
end)
end

1 Like

Why not check if it’s a base part?

3 Likes

That’s an example. Some base parts have properties that others don’t, which it would then be useful for that, but there are usually always ways to get around pcalls like that

1 Like

Pcalls are not only for web-related stuff.
When you have an infinite loop in a server script that handles an important task related to gameplay, it’s extremely important to use a pcall.
This way you’re gonna prevent your game from breaking randomly, when occasionally something errors.

BAD way

task.spawn(function()
  pcall(function()
    while true do
      --...
    end
  end
end)

GOOD way

task.spawn(function()
    while true do
      pcall(function()
        --...
      end)
    end
end)
3 Likes

You’re right that’s a more efficient way of doing it.

1 Like

Pretty sure this should be in #help-and-feedback:scripting-support.

PCall stands for protected call, it’s basically used to make sure a function doesn’t error, as errors stop the script from continuing.

1 Like

I usually use Promises since they add so much more versatality to handling asynchronous/unsafe coroutining than vanilla pcalls do.

For example, this would take a ton more lines of code to write in vanilla per function!

function GetHumanoidDescription(UserId)
	return Promise.new(function(Resolve, Reject, OnCancel)
		local Thumbnail
		local Success, Error = pcall(function()
			Thumbnail = game:GetService("Players"):GetHumanoidDescriptionFromUserId(UserId)
		end)
		
		if Success then
			Resolve(Thumbnail)
		else
			Reject(Error)
		end
		
		OnCancel(function()
			Reject("Cancelled GetHumanoidDescription for "..UserId)
		end)
	end)
end

function OnFinish(Array)
	print(Array)
end

Promise.all {
	GetHumanoidDescription(1),
	GetHumanoidDescription(2),
	GetHumanoidDescription(4), -- errors, but we are good
}:andThen(OnFinish):catch(warn)

It would probably be more efficient if you just tagged each instance you want to use with CollectionService instead of looping through every descendant and brute forcing it.

4 Likes

I still dont know why people prefer to use bad practice as mentioned in the original post , over a safer method. Why is that? People are that lazy?

1 Like

You’ll definitely need to Pcall specific stuff such as UserOwnsGamePassAsync:

local market = game:GetService("MarketplaceService")

local success, ownsGamepass = pcall(function()
	return market:UserOwnsGamePassAsync(userId, gamepassId)
end)

if success then
	print(ownsGamepass) 
end
  • This should be moved to scripting support! :+1:
2 Likes

Moved it :+1:

If anyone has a suitable answer to why people still use and do bad practice and not listen to people who try to help them have a better and safer code

1 Like

To be honest, before this post I didn’t really know pcalls simplified code like that. I’d usually just have a lot of checks to make sure nothing errors, but if something did somehow error, it would probably end up ruining the whole code.

Since I’m new to pcalls if you have a game loop (a system to get people in games that needs some player info that might be nil) should you use a pcall?

1 Like

I believe it is partially because they ‘look scary’.

In addition, most people learn about pcalls when they learn about datastores, so they tend to think pcalls are only for datastores or, because they just copy code instead of learning why that code is how it is, they never really understand the importance of this incredible little tool.

1 Like

I don’t use pcalls unless they are necessary, and I don’t think anyone else should use them unless there’s a real point to it. In my current project (est. 53k lines of code, just for scaling perspective), I’m only using pcalls about a dozen times (I use them when adjusting some core stuff (ex: StarterGui:SetCore), MarketplaceSerivce or GroupService calls (mentioned already above, basically just HTTP request stuff), a niche use case of checking whether properties exist, and then when modifying the ProcessReceipt callback, because it’s very important that errors are able to be handled in that situation.

However…

I will admit that I might be a bit of an outlier, because I aggressively check my functions and code for bad arguments, strange values, and necessary bits for my code to function.

Example


The custom warn function there just calls debug.trackback, because it makes it easier to see where errors are stemming from and debug stuff from it

So, I kind of agree, but I also disagree. I think it’s important to make sure that your game won’t randomly crash and collapse, because someone decides to give your neat code some weird input. But, I think it’s much better to handle that with your own coded solutions vice simply using a pcall. For example, wrapping a large function in a pcall doesn’t seem to make a lot of sense to me - it seems much better to just make frequent checks a coding habit and leave pcalls for external things. It lets you debug better and more efficiently, at least imo.

(Also, cause I know there was some back and forth, this should go in #resources:community-resources - this section is intended for people to get help on their coding creations/code that is erroring + it’s more likely to be buried here. Love the thread as a dialogue piece though, I think it’s important that people share and discuss good coding habits [as well as the situations appropriate for each - it brings us all up together and we all learn something, so please keep it up!])

2 Likes