You should always resolve or reject a promise so that any code thats blocking on the promise will not block.

You can get a general understanding of promises from MDN, the promise implementation used by Cfx works in (relatively) the same way (Cfx’s implementation doesn’t have a then it has next, you can handle failed promises in next too)

CFX_CORE = {}

local function init_has_player_loaded()
	CFX_CORE.player_data = nil
	-- it should be noted that we can only use promises within valid coroutines
	-- such as `CreateThread`
	local p = promise.new()
	CFX_CORE.has_player_loaded = p
	-- we only care about setting the player data
	p:next(function(plyData)
		CFX_CORE.player_data = plyData
	end, function (err)
		-- handle error
	end)
end
-- we want to create all of our data on the initial resource tick,
-- `CreateThread` will execute after the first tick.
CreateThreadNow(init_has_player_loaded)

-- reset our player loaded data so we'll await again on functions requiring a
-- valid `player_data` object
RegisterNetEvent("CFX_CORE:player_unloaded", init_has_player_loaded)

RegisterNetEvent("CFX_CORE:player_loaded", function(plyData)
	CFX_CORE.has_player_loaded:resolve(plyData)
end)

CreateThread(function()
	while true do
		-- wait for player_data to be initialized
		local player_data = Citizen.Await(CFX_CORE.has_player_loaded)
		-- do something that relies on the player having loaded
		Wait(0)
	end
end)

1 Like