Janitor
Janitor is a light-weight, flexible object for cleaning up connections, instances, or anything. This implementation covers all use cases, as it doesn't force you to rely on naive typechecking to guess how an instance should be cleaned up. Instead, the developer may specify any behavior for any object.
Functions
Is
Janitor.Is(Object: any--
The object you are checking.
) → boolean--
true if Object is a Janitor.
Determines if the passed object is a Janitor. This checks the metatable directly.
new
Instantiates a new Janitor object.
Add
Janitor:Add(Object: T,--
The object you want to clean up.
MethodName?: string | true,--
The name of the method that will be used to clean up. If not passed, it will first check if the object's type exists in TypeDefaults, and if that doesn't exist, it assumes Destroy.
Index?: any--
The index that can be used to clean up the object manually.
) → T--
The object that was passed as the first argument.
Adds an Object to Janitor for later cleanup, where MethodName is the key of the method within Object which should be called at cleanup time.
If the MethodName is true the Object itself will be called instead. If passed an index it will occupy a namespace which can be Remove()d or overwritten.
Returns the Object.
info
Objects not given an explicit MethodName will be passed into the typeof function for a very naive typecheck.
RBXConnections will be assigned to "Disconnect", functions will be assigned to true, and everything else will default to "Destroy".
Not recommended, but hey, you do you.
local Workspace = game:GetService("Workspace")
local TweenService = game:GetService("TweenService")
local Obliterator = Janitor.new()
local Part = Workspace.Part
-- Queue the Part to be Destroyed at Cleanup time
Obliterator:Add(Part, "Destroy")
-- Queue function to be called with `true` MethodName
Obliterator:Add(print, true)
-- This implementation allows you to specify behavior for any object
Obliterator:Add(TweenService:Create(Part, TweenInfo.new(1), {Size = Vector3.new(1, 1, 1)}), "Cancel")
-- By passing an Index, the Object will occupy a namespace
-- If "CurrentTween" already exists, it will call :Remove("CurrentTween") before writing
Obliterator:Add(TweenService:Create(Part, TweenInfo.new(1), {Size = Vector3.new(1, 1, 1)}), "Destroy", "CurrentTween")
import { Workspace, TweenService } from "@rbxts/services";
import { Janitor } from "@rbxts/janitor";
const Obliterator = new Janitor<{ CurrentTween: Tween }>();
const Part = Workspace.FindFirstChild("Part") as Part;
// Queue the Part to be Destroyed at Cleanup time
Obliterator.Add(Part, "Destroy");
// Queue function to be called with `true` MethodName
Obliterator.Add(print, true);
// This implementation allows you to specify behavior for any object
Obliterator.Add(TweenService.Create(Part, new TweenInfo(1), {Size: new Vector3(1, 1, 1)}), "Cancel");
// By passing an Index, the Object will occupy a namespace
// If "CurrentTween" already exists, it will call :Remove("CurrentTween") before writing
Obliterator.Add(TweenService.Create(Part, new TweenInfo(1), {Size: new Vector3(1, 1, 1)}), "Destroy", "CurrentTween");
AddPromise
Janitor:AddPromise(PromiseObject: Promise--
The promise you want to add to the Janitor.
) → PromiseAdds a Promise to the Janitor. If the Janitor is cleaned up and the Promise is not completed, the Promise will be cancelled.
local Obliterator = Janitor.new()
Obliterator:AddPromise(Promise.delay(3)):andThenCall(print, "Finished!"):catch(warn)
task.wait(1)
Obliterator:Cleanup()
import { Janitor } from "@rbxts/janitor";
const Obliterator = new Janitor();
Obliterator.AddPromise(Promise.delay(3)).andThenCall(print, "Finished!").catch(warn);
task.wait(1);
Obliterator.Cleanup();
Remove
Cleans up whatever Object was set to this namespace by the 3rd parameter of Janitor.Add.
local Obliterator = Janitor.new()
Obliterator:Add(workspace.Baseplate, "Destroy", "Baseplate")
Obliterator:Remove("Baseplate")
import { Workspace } from "@rbxts/services";
import { Janitor } from "@rbxts/janitor";
const Obliterator = new Janitor<{ Baseplate: Part }>();
Obliterator.Add(Workspace.FindFirstChild("Baseplate") as Part, "Destroy", "Baseplate");
Obliterator.Remove("Baseplate");
Get
Janitor:Get(Index: any--
The index that the object is stored under.
) → any?--
This will return the object if it is found, but it won't return anything if it doesn't exist.
Gets whatever object is stored with the given index, if it exists. This was added since Maid allows getting the task using __index.
local Obliterator = Janitor.new()
Obliterator:Add(workspace.Baseplate, "Destroy", "Baseplate")
print(Obliterator:Get("Baseplate")) -- Returns Baseplate.
import { Workspace } from "@rbxts/services";
import { Janitor } from "@rbxts/janitor";
const Obliterator = new Janitor<{ Baseplate: Part }>();
Obliterator.Add(Workspace.FindFirstChild("Baseplate") as Part, "Destroy", "Baseplate");
print(Obliterator.Get("Baseplate")); // Returns Baseplate.
Cleanup
Janitor:Cleanup() → ()
Calls each Object's MethodName (or calls the Object if MethodName == true) and removes them from the Janitor. Also clears the namespace.
This function is also called when you call a Janitor Object (so it can be used as a destructor callback).
Obliterator:Cleanup() -- Valid.
Obliterator() -- Also valid.
Obliterator.Cleanup()
Destroy
Janitor:Destroy() → ()Calls Janitor.Cleanup and renders the Janitor unusable.
warning
Running this will make any attempts to call a function of Janitor error.
LinkToInstance
Janitor:LinkToInstance(AllowMultiple?: boolean--
Whether or not to allow multiple links on the same Janitor.
) → RbxScriptConnection--
A pseudo RBXScriptConnection that can be disconnected to prevent the cleanup of LinkToInstance.
"Links" this Janitor to an Instance, such that the Janitor will Cleanup when the Instance is Destroyed() and garbage collected.
A Janitor may only be linked to one instance at a time, unless AllowMultiple is true. When called with a truthy AllowMultiple parameter,
the Janitor will "link" the Instance without overwriting any previous links, and will also not be overwritable.
When called with a falsy AllowMultiple parameter, the Janitor will overwrite the previous link which was also called with a falsy AllowMultiple parameter, if applicable.
local Obliterator = Janitor.new()
Obliterator:Add(function()
print("Cleaning up!")
end, true)
do
local Folder = Instance.new("Folder")
Obliterator:LinkToInstance(Folder)
Folder:Destroy()
end
import { Janitor } from "@rbxts/janitor";
const Obliterator = new Janitor();
Obliterator.Add(() => print("Cleaning up!"), true);
{
const Folder = new Instance("Folder");
Obliterator.LinkToInstance(Folder, false);
Folder.Destroy();
}
This returns a mock RBXScriptConnection (see: RbxScriptConnection).
LinkToInstances
Janitor:LinkToInstances() → Janitor--
A new Janitor that can be used to manually disconnect all LinkToInstances.
Links several instances to a new Janitor, which is then returned.