Task Queue Module
https://create.roblox.com/store/asset/18332916329
Overview
The TaskQueue
module is designed to manage and execute tasks sequentially in Roblox. This is particularly useful in scenarios where tasks must be performed one at a time to avoid conflicts, ensure order, or manage resources effectively. The module allows you to enqueue functions (tasks) along with their arguments, ensuring that each task completes before the next one starts.
Module Script
Here’s the TaskQueue
module script, which should be placed in ServerScriptService
:
-- ModuleScript in ServerScriptService
local TaskQueue = {}
TaskQueue.__index = TaskQueue
function TaskQueue.new()
local self = setmetatable({}, TaskQueue)
self._queue = {}
self._size = 0
self._processing = false
return self
end
function TaskQueue:Enqueue(taskFunction, ...)
local args = {...}
table.insert(self._queue, function()
taskFunction(unpack(args))
end)
self._size = self._size + 1
self:ProcessQueue()
end
function TaskQueue:Dequeue()
if self._size == 0 then
error("Queue is empty")
end
local task = table.remove(self._queue, 1)
self._size = self._size - 1
return task
end
function TaskQueue:ProcessQueue()
if not self._processing and self._size > 0 then
self._processing = true
coroutine.wrap(function()
while self._size > 0 do
local task = self:Dequeue()
task()
end
self._processing = false
end)()
end
end
function TaskQueue:Size()
return self._size
end
function TaskQueue:IsEmpty()
return self._size == 0
end
function TaskQueue:Clear()
self._queue = {}
self._size = 0
end
return TaskQueue
How to Use the Task Queue Module
- Require the Module: First, require the module in your script.
- Create a Task Queue Instance: Instantiate a new task queue.
-
Enqueue Tasks: Add tasks to the queue using the
Enqueue
method. - Process Tasks: The module automatically processes tasks in the order they were added.
Example Usage
Here’s an example of how to use the TaskQueue
module in a script:
-- Script in ServerScriptService
local TaskQueue = require(game.ServerScriptService:WaitForChild("TaskQueue"))
local myQueue = TaskQueue.new()
-- Define some tasks
local function Task1()
print("Starting Task 1")
wait(2)
print("Completed Task 1")
end
local function Task2(arg1, arg2)
print("Starting Task 2 with arguments:", arg1, arg2)
wait(3)
print("Completed Task 2")
end
local function Task3()
print("Starting Task 3")
wait(1)
print("Completed Task 3")
end
-- Enqueue tasks with arguments
myQueue:Enqueue(Task1)
myQueue:Enqueue(Task2, "Hello", "World")
myQueue:Enqueue(Task3)
-- The tasks will be processed in order
In this example:
- Task1: A simple task that prints messages and waits for 2 seconds.
- Task2: A task that prints messages with arguments and waits for 3 seconds.
- Task3: Another simple task that prints messages and waits for 1 second.
The tasks are enqueued and will be executed in the order they were added. Task1 will complete before Task2 starts, and Task2 will complete before Task3 starts.
Use Case Examples
-
Order Processing System: If you’re developing a game with an order processing system, you might want to ensure that orders are processed one at a time to avoid race conditions or data inconsistencies.
local function ProcessOrder(orderId) print("Processing order:", orderId) wait(2) -- Simulate processing time print("Order processed:", orderId) end myQueue:Enqueue(ProcessOrder, 1) myQueue:Enqueue(ProcessOrder, 2) myQueue:Enqueue(ProcessOrder, 3)
-
Sequential Animations: When creating a sequence of animations or events that should play one after another, the task queue ensures they don’t overlap.
local function PlayAnimation(animation) print("Playing animation:", animation.Name) wait(animation.Length) -- Simulate animation length print("Animation completed:", animation.Name) end local anim1 = {Name = "Jump", Length = 1} local anim2 = {Name = "Run", Length = 2} local anim3 = {Name = "Wave", Length = 1.5} myQueue:Enqueue(PlayAnimation, anim1) myQueue:Enqueue(PlayAnimation, anim2) myQueue:Enqueue(PlayAnimation, anim3)
-
Resource Management: If your game has limited resources (like spawning limited entities), you can use a task queue to ensure resource creation is handled properly.
local function SpawnEntity(entityType) print("Spawning entity:", entityType) wait(1) -- Simulate spawning time print(entityType, "spawned") end myQueue:Enqueue(SpawnEntity, "Zombie") myQueue:Enqueue(SpawnEntity, "Skeleton") myQueue:Enqueue(SpawnEntity, "Dragon")
Roblox provides built-in mechanisms for handling coroutines and asynchronous tasks, but it doesn’t natively provide a high-level task queue system out of the box. Here’s a brief overview of Roblox’s native capabilities and why you might still want to use a custom task queue module:
Doesn’t Roblox already support coroutines natively?
-
Coroutines: Roblox uses Lua, which supports coroutines natively. Coroutines allow for cooperative multitasking by yielding execution and resuming later.
local function exampleCoroutine() print("Coroutine started") wait(2) print("Coroutine resumed after wait") end local co = coroutine.create(exampleCoroutine) coroutine.resume(co)
-
Promises: Roblox also provides the
Promise
library throughPromise.new
, which allows for managing asynchronous tasks in a more structured way, similar to JavaScript’sPromise
.local Promise = require(game.ReplicatedStorage.Promise) Promise.new(function(resolve, reject) wait(2) resolve("Task completed") end):andThen(function(result) print(result) end):catch(function(err) warn(err) end)
Why Use a Custom Task Queue Module?
While coroutines and promises are powerful, they require manual management of task flow. A custom task queue module abstracts this complexity and provides benefits such as:
-
Sequential Task Execution: Ensures that tasks are executed one after another, without needing to manage coroutine states or promise chains manually.
-
Task Management: Simplifies enqueuing, dequeuing, and processing tasks with arguments, making code more maintainable and readable.
-
Error Handling: Centralizes error handling for all tasks, making it easier to manage and debug.
-
Resource Management: Helps manage resources by ensuring tasks are not started until the previous ones are completed, preventing race conditions and resource conflicts.
Conclusion
The TaskQueue
module is a robust solution for managing sequential tasks in Roblox. By encapsulating tasks and ensuring they are processed one at a time, you can maintain order and prevent conflicts in various scenarios. This module is versatile and can be adapted to numerous use cases, from simple print statements to complex game mechanics.
If you have any questions at all, absolutely feel free to ask and I will answer to the best of my ability.
Edit: I do plan on adding the ability to iterate through tables of functions. For the time being just make the table yourself and insert the functions and then just use a for loop to create the task for each one.