Custom Signal Class

local CustomEvent = {}

function CustomEvent.new()
	local self = {}
	self.Value = nil
	self.Connections = {}
	return setmetatable(self, { __index = CustomEvent })
end

function CustomEvent:Connect(func)
	local connection = { func = func }
	self.Connections[connection] = connection
	return connection
end

function CustomEvent:Fire(...)
	self.Value = ...
	local Connections = self.Connections
	if #Connections >= 0 or Connections ~= nil then
		for _, connection in pairs(Connections) do
			task.spawn(function()
				connection.func(self.Value)
			end)
		end
	end
end

function CustomEvent:Wait(...)
	local thread = coroutine.running()
	local connection

	connection = self:Connect(function(...)
		self:Disconnect(connection)
		coroutine.resume(thread, ...)
	end)

	return coroutine.yield()
end

function CustomEvent:Once(connection, ...)
	self.Value = ...
	local Connections = self.Connections
	local conn = Connections[connection]
	conn.func(self.Value)
	Connections[connection] = nil
end

function CustomEvent:Disconnect(connection)
	local Connections = self.Connections
	Connections[connection] = nil
end

return CustomEvent

I made a Signal Class, and would like to get some feedback

1 Like

Havent got time to take a proper look at it, but shouldnt it be greater than 0 not greater than or equal to 0,

but other wise looks pretty cool

self.Value seems redundant. Whenever you reference it, you are typically defining it at the start of a function’s code block and then doing something with it at the end. From what I can see, there isn’t ever a case where you define it in one function and retrieve it somewhere else, so I’m not sure why you’re indexing the Signal and storing that information.

To be clearer with what I’m saying, I’m not sure why the code looks like:

function CustomEvent:Fire(...)
	self.Value = ...
	local Connections = self.Connections
	if #Connections >= 0 or Connections ~= nil then
		for _, connection in pairs(Connections) do
			task.spawn(function()
				connection.func(self.Value)
			end)
		end
	end
end

When this appears functionally the same:

function CustomEvent:Fire(...)
	local Connections = self.Connections
	if #Connections >= 0 or Connections ~= nil then
		for _, connection in pairs(Connections) do
			task.spawn(function()
				connection.func(...)
			end)
		end
	end
end

Would also recommend editing the thread to move this to #help-and-feedback:code-review

ReplicatedStorage.CustomEventSignal:22: Cannot use ‘…’ outside of a vararg function - Studio - CustomEventSignal:22
10:03:54.929 Requested module experienced an error while loading - Server -

This is the error I kept getting when I did that.

task.spawn(function()
				connection.func(...)
			end)

In that case, just define it locally to fix the issue, e.g.:

function CustomEvent:Fire(...)
	local Arguments = {...}
	local Connections = self.Connections
	if #Connections >= 0 or Connections ~= nil then
		for _, connection in pairs(Connections) do
			task.spawn(function()
				connection.func(table.unpack(Arguments)
			end)
		end
	end
end
2 Likes