{"id":"tpc9000/async","name":"async","scope":"tpc9000","platform":"roblox","description":"Mirrored from the Wally registry.","version":"0.4.1","latest":"0.4.1","versions":["0.1.0","0.1.1","0.1.2","0.1.3","0.1.4","0.1.5","0.1.6","0.1.7","0.1.8","0.1.9","0.1.10","0.1.11","0.1.12","0.2.0","0.2.1","0.3.0","0.3.1","0.4.0","0.4.1"],"license":"MIT","licenseRating":"safe","licenseCaveats":[],"licenseVerified":true,"dependencies":{"tpc9000/typeguard":{"version":"^6.0.0-alpha.2","alias":"TypeGuard"}},"integrity":"7ab365976a8c031accdb529645954b6fe714a94c37200948902f2a1436573fd1","likes":0,"downloads":0,"install":"forest install tpc9000/async","url":"https://forest.dev/p/roblox/tpc9000/async","files":"https://api.forest.dev/ai/package/roblox/tpc9000/async/files","readme":"# Async\r\n\r\nA tree-based thread lifecycle library which sits on top of the Roblox task library.\r\n\r\n## 1: Spawning Threads & Cleanup Handlers\r\n\r\n```lua\r\nlocal function Animate(Item, Damping, Frequency, Properties)\r\n    -- ...\r\nend\r\n\r\nlocal TestAnimation = Async.Spawn(function()\r\n    local function InitialState()\r\n        Animate(Workspace.Part1, 1, 5, {\r\n            Position = Vector3.new(0, 10, 0);\r\n        })\r\n        Animate(Workspace.Part2, 1, 100, {\r\n            Position = Vector3.new(0, 10, 0);\r\n        })\r\n    end\r\n\r\n    Async.OnFinish(InitialState)\r\n    InitialState()\r\n\r\n    local function AnimatePart1()\r\n        for Step = 1, 3 do\r\n            Animate(Workspace.Part1, 1, 5, {\r\n                Position = Vector3.new(0, 10 + 10 * Step, 0);\r\n            })\r\n\r\n            task.wait(1)\r\n        end\r\n    end\r\n\r\n    local function AnimatePart2()\r\n        for Step = 1, 3 do\r\n            Animate(Workspace.Part2, 1, 100, {\r\n                Position = Vector3.new(0, 10 + 10 * Step, 0);\r\n            })\r\n\r\n            task.wait(1)\r\n        end\r\n    end\r\n\r\n    task.wait(1) -- 1 sec delay before animation starts\r\n\r\n    Async.Spawn(AnimatePart1)\r\n    Async.Spawn(AnimatePart2)\r\nend)\r\n\r\ntask.wait(2)\r\n\r\n-- This will not only cancel the animation thread, but also the sub-threads\r\n-- which the animation thread spawned (AnimatePart1, AnimatePart2). When\r\n-- cancelled, it will call OnFinish, and reset the animation to the initial\r\n-- state (InitialState).\r\nAsync.Cancel(TestAnimation)\r\n```\r\n\r\n## 2: Waiting for Thread Results\r\n\r\n```lua\r\nlocal Success, Result = Async.Await(Async.Spawn(function()\r\n    local Value = math.random()\r\n    task.wait(2)\r\n\r\n    if (Value > 0.5) then\r\n        return Value\r\n    end\r\n\r\n    error(\"<FAIL_TAG>\") -- Surrounding alphanumeric + underscore with < & > will capture the tag in the error message without all the mess.\r\nend))\r\n\r\nprint(Success, Result)\r\n```\r\n\r\n## 3: Waiting for All Thread Results\r\n\r\n```lua\r\nprint(Async.AwaitAll({\r\n    Async.Spawn(function()\r\n        task.wait(1)\r\n        return \"Delayed\"\r\n    end);\r\n    Async.Spawn(function()\r\n        return \"Immediate\"\r\n    end);\r\n}))\r\n--> {{true, \"Immediate\"}, {true, \"Delayed\"}}\r\n```\r\n\r\n## 4: Waiting for First Thread Result\r\n\r\n```lua\r\nprint(Async.AwaitFirst({\r\n    Async.Spawn(function()\r\n        task.wait(1)\r\n        return \"Last\"\r\n    end);\r\n    Async.Spawn(function()\r\n        return \"First\"\r\n    end);\r\n}))\r\n--> true, \"First\"\r\n```\r\n\r\n## 5: Blockable Timers\r\n\r\n```lua\r\nlocal Characters = {}\r\nlocal Stop = Async.Timer(1, function()\r\n    table.clear(Characters)\r\n\r\n    for _, Player in game.Players:GetChildren() do\r\n        local Char = Player.Character\r\n\r\n        if (not Char) then\r\n            return\r\n        end\r\n\r\n        table.insert(Characters, Char)\r\n    end\r\nend, \"FindPlayers\")\r\n-- \"FindPlayers\" will show up in the Microprofiler, though always ensure the timer does not block if the tag is specified\r\n\r\nAsync.Delay(5, Stop)\r\n```\r\n","readmeTruncated":false}