This line doesn't get all the player's stats instantly

local top = dataStorePages:GetCurrentPage()

for a,b in pairs(top) do
	local userid = b.key
	local wins = b.value
	local username = "[Failed To Load]"
	local s,e = pcall(function()
		username = game.Players:GetNameFromUserIdAsync(userid)
	end)
	if not s then
		warn("Error getting name for "..userid..". Error: "..e)
	end
	local image = game.Players:GetUserThumbnailAsync(userid, Enum.ThumbnailType.HeadShot, Enum.TmbnailSize.Size150x150)
	table.insert(data,{username,wins,image})
    print('....y e s')
end

Info, elaborations, considerations.

  • It’s a script inside serverscriptservice
  • It’s makes the GUI global leaderboard function.

Trying to make a leaderboard but when I add a print, I realized it delays like every I’m assuming .5 seconds to get 1 player’s info. It never goes past those lines of code so I want to get it instantly. This is the cause because it’s in a long yield until there are 100 players and it will never load the players’ global leaderboard so I’m saying that I can’t fix it, any solutions?

Try coroutining in the loop?

for a,b in pairs(top) do
	coroutine.wrap(function()
		local userid = b.key
		local wins = b.value
		local username = "[Failed To Load]"
		local s,e = pcall(function()
			username = game.Players:GetNameFromUserIdAsync(userid)
		end)
		if not s then
			warn("Error getting name for "..userid..". Error: "..e)
		end
		local image = game.Players:GetUserThumbnailAsync(userid, Enum.ThumbnailType.HeadShot, Enum.TmbnailSize.Size150x150)
		table.insert(data,{username,wins,image})
		print('....y e s')
	end)()
end
2 Likes

2 minutes response and it works, ty.

2 Likes

Anytime! If you have anymore issues don’t be afraid to make another post!

Also yea, I would try to find a way to somehow improve your code in a way as @EssenceExplorer mentioned to get a bit more speed from it

1 Like

I think I should be continuing this instead of making another post because this is same topic about this so there’s no point about making a new one, to what at least I think.

The problem is that in this while wait 60 do loop, when it prints only 1 player’s stat, it skips the other 99 stats that are inside the page and waits for the other prints to complete. After the loop is done, it gets 99 more stats like it just forgotten to, I’m trying to say that it doesn’t load 99 more players.

image

Hmm, what’s the code that you have as of now?

It’s this

Code
local dataStoreService = game:GetService("DataStoreService")
local dataStore = dataStoreService:GetOrderedDataStore("Datastore1")
local sample = script:WaitForChild("Sample")

spawn(function() 
	while true do

		for i,plr in pairs(game.Players:GetPlayers()) do
			if plr.UserId>0 then--Prevent errors
				local w = plr.leaderstats.Wins.Value--Get value
				if w then
					pcall(function()
						--Wrap in a pcall so if Roblox is down, it won't error and break.
						dataStore:UpdateAsync(plr.UserId,function(oldVal)
							--Set new value
							return tonumber(w)
						end)
					end)
				end
			end
		end    

		local smallestFirst = false
		local numberToShow = 100
		local minValue = 0
		local maxValue = 10e30
		local pages = dataStore:GetSortedAsync(smallestFirst, numberToShow, minValue, maxValue)

		local top = pages:GetCurrentPage()

		local data = {}
		for a,b in pairs(top) do
			coroutine.wrap(function()
				local userid = b.key
				local wins = b.value
				local username = "[Failed To Load]"
				local s,e = pcall(function()
					username = game.Players:GetNameFromUserIdAsync(userid)
				end)
				if not s then
					warn("Error getting name for "..userid..". Error: "..e)
				end
				local image = game.Players:GetUserThumbnailAsync(userid, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size150x150)
				table.insert(data,{username,wins,image})
				print('....y e s')
			end)()
		end

		print("b")
		for i,v in pairs(game.Players:GetDescendants()) do
			if v:IsA("UIListLayout") and v.Name == "UI" then
				local scriptSave = v.Parent.Parent:FindFirstChild("GUIActivate")

				if scriptSave ~= nil then
					v.Parent = scriptSave
					print("do the parent!!!")
				end
			end
		end

		print("is the completed")
		for i,v in pairs(game.Players:GetDescendants()) do
			if v:IsA("ScrollingFrame") and v.Name == "GlobalFrame" then
				v:ClearAllChildren()
			end
		end
		print("it do children clear cler")

		for i,v in pairs(game.Players:GetDescendants()) do
			if v:IsA("UIListLayout") and v.Name == "UI" then
				local frame = v.Parent.Parent:FindFirstChild("GlobalFrame")

				if frame ~= nil then
					v.Parent = frame
				end
			end
		end
		print("do the parent again")

		for number,d in pairs(data) do
			local name = d[1]
			local val = d[2]
			local image = d[3]
			local color = Color3.new(1,1,1)--Default color
			if number == 1 then
				color = Color3.new(1,1,0)--1st place color
			elseif number == 2 then
				color = Color3.new(0.9,0.9,0.9)--2nd place color
			elseif number == 3 then
				color = Color3.fromRGB(166, 112, 0)--3rd place color
			end
			local new = sample:Clone()
			new.Name = name
			new.LayoutOrder = number
			new.Image.Image = image
			new.Image.Place.Text = number
			new.Image.Place.TextColor3 = color
			new.PName.Text = name
			new.Value.Text = "Wins: "..val
			new.Value.TextColor3 = color
			new.PName.TextColor3 = color

			for i,v in pairs(game.Players:GetDescendants()) do
				if v:IsA("ScrollingFrame") and v.Name == "GlobalFrame" then
					new.Parent = v
					print("sets 1 player of plr frame")
				end
			end

		end
		print("100 PLAYERSI NSIDE THE THING")

		wait(60)
	end

end)

Hmm, maybe try coroutining a partial bit of the loop’s contents instead of all of it?

for a,b in pairs(top) do
	local userid = b.key
	local wins = b.value
	local username = "[Failed To Load]"
	local s,e = pcall(function()
		username = game.Players:GetNameFromUserIdAsync(userid)
	end)
	if not s then
		warn("Error getting name for "..userid..". Error: "..e)
	end
	coroutine.wrap(function()
		local image = game.Players:GetUserThumbnailAsync(userid, Enum.ThumbnailType.HeadShot, Enum.ThumbnailSize.Size150x150)
		table.insert(data,{username,wins,image})
		print('....y e s')
	end)()
end
1 Like

Now it gives the same problem the post has been created (waits .5 seconds to get 1 player’s stats)

It’s probably due to the `GetNameFromUserIdAsync taking a while, you could put the related code in another coroutine and see if that does anything, but it would still probably have that same issue mentioned before. Is there no way to give it a table containing the wins and the name of the player as a table for the value instead of just the wins?

Sorry I having a hard time trying to understand this statement and how will that help.

There’s no real way for it to go faster if it has to use a yielding function such as GetNameFromUserIdAsync, again, you could also coroutine it, but the issue you had before of one player’s data being done and the rest finishing 60 seconds later may still happen.

I’m not sure how much giving a table containing the wins and the name of the player as the data’s value instead of only the wins will help, it will reduce an Async call sure, but it’ll still have to get the UserThumbnail, which may still mess up the code, and storing the name and even the Image url will have issues if the Username changes their name or their avatar, so it’s not advised now that I think about it.

The only thing I could really recommend is caching results so if you already have their name and/or their image url, no need to request for it again, GetNameFromUserIdAsync explains how you could do a simple caching system, maybe try to make something similar for both the name and the Image url, so times will be much faster. Sure the first time will still be slow as the cache will be empty, but afterwards, it would be smooth sailing

What confused me the most is it was working and it gets the stats instantly before. It was inside a GUI but I’m not sure if I should be putting it on one script so I decided to just rewrite the code because it sends warnings of sending key request and it happens because it doubles whenever there are 2 players which would cause because of using updateasync to update the player’s stat so It will be saved and be on the leaderboard, which means I have to do that.

I really don’t know why because I wasn’t really rewriting it, I was just copying and pasting codes that are needed like the code that has the error at the moment and still have different results.

To add on to what has already been said here, is there a reason why you cannot save the username alongside the UserID? If you saved the username you wouldn’t have to wait for GetNameFromUserIdAsync to finish.

Not anything there is saved or updated at all except the Win value (or the value that is used for the leaderboard)

I don’t think I should be saving and I would still go for GetNameFromUserIdAsync because it worked instantly before I merge my script from a GUI script into a ServerScriptService script and it’s confusing me that it is the function that delays now. (Not GetUserThumbnalAsync because it’s instant.)

You’ll probably want to create a caching system like @EmbatTheHybrid said. Just to clarify, since the leaderboard is global, you are saving the top 100 players in a DataStore, correct?

As the documentation says GetNameFromUserIdAsync queries the website and pauses the thread until it gets a response. There’s inevitably going to be some form of delay when that happens. Whether or not it’s noticeable is different, but in your case it seems like it is. As to why GetUserThumbnailAsync is instant, I can’t really tell you without knowing what is going on behind the scenes.

1 Like

One solution you could try is waiting for all the data to be queried, and then update the UI.

Assuming this is a global leaderboard, you won’t be updating much more than once a minute, so you can removing the flashing / loading problem entirely by updating after you get the data. While it may be behind a few seconds, the reality is the player won’t notice the difference and you remove the loading issue with the UI.


My best bet is that is only retrieves the rbxthumb string for the source, which is just a formatted string. It’s not doing any actual image fetching until you put it in an ImageLabel or preload it.

1 Like

Correct.

I still find it odd to why my current is never the same thing to the old script like I previously mention so i’ll just try caching I guess.

What you could do is save the username and the image URL alongside the wins. Use that saved data to instantly update the values on the leaderboard, and in the background cross check it with GetNameFromUserIdAsync - if you want to make sure that you always have the most recent username. By doing that you would be able to load the leaderboard quickly, and then only have a delay in which usernames update if the player has changed their username recently.

You said that it originally worked before merging the script, would you mind clarifying what the original scripts looked like?

I don’t really get to what you mean by the flashing loading problem. Also to let you know, the main problem right now is to why it cause a delay every 0.5 seconds which would make the leaderboard GUI not load the player stats, not load the roblox ui though ONLY IF you’re talking about that. It just will never load the player stats so that’s what I’m saying.

1 Like