### Quick Installation Script for Roblox Studio Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/Installation.md Automatically downloads and installs the Promise library as a ModuleScript in Roblox Studio. Requires HTTP enabled and a selected folder or ServerScriptService as target. Sets the created module as the current selection. ```Lua local Http = game:GetService("HttpService") local HttpEnabled = Http.HttpEnabled Http.HttpEnabled = true local m = Instance.new("ModuleScript") m.Parent = game:GetService("Selection"):Get()[1] or game:GetService("ServerScriptService") m.Name = "Promise" m.Source = Http:GetAsync("https://raw.githubusercontent.com/evaera/roblox-lua-promise/master/lib/init.lua") game:GetService("Selection"):Set({m}) Http.HttpEnabled = HttpEnabled ``` -------------------------------- ### Cancellable Animation Sequence in Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/Examples.md Provides an example of a composable, cancellable animation sequence in Lua using promises, ensuring instant completion on cancellation. Requires Promise library, TweenService, and Roblox workspace. Inputs are a part and intensity level; outputs promise chains with animations. Heavily reliant on promise chaining for composability. ```lua local Promise = require(game.ReplicatedStorage.Promise) local TweenService = game:GetService("TweenService") local sleep = Promise.promisify(wait) function apply(obj, props) for key, value in pairs(props) do obj[key] = value end end function runTween(obj, props) return Promise.new(function(resolve, reject, onCancel) local tween = TweenService:Create(obj, TweenInfo.new(0.5), props) if onCancel(function() tween:Cancel() apply(obj, props) end) then return end tween.Completed:Connect(resolve) tween:Play() end) end function runAnimation(part, intensity) return Promise.resolve() :finallyCall(sleep, 1) :finallyCall(runTween, part, { Reflectance = 1 * intensity }):finallyCall(runTween, part, { CFrame = CFrame.new(part.Position) * CFrame.Angles(0, math.rad(90 * intensity), 0) }):finallyCall(runTween, part, { Size = ( Vector3.new(10, 10, 10) * intensity ) + Vector3.new(1, 1, 1) }) end local animation = Promise.resolve() -- Begin Promise chain :finallyCall(runAnimation, workspace.Part, 1) :finallyCall(sleep, 1) :finallyCall(runAnimation, workspace.Part, 0) :catch(warn) wait(2) animation:cancel() -- Remove this line to see the full animation ``` -------------------------------- ### Promise Chaining in Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/Examples.md Demonstrates chaining multiple promise-returning functions in Lua, allowing sequential execution and centralized error handling. Dependencies include the Promise library. Inputs are promise-returning functions; outputs are the final result or caught errors. Not suitable for synchronous operations. ```lua doSomething() :andThen(doSomethingElse) :andThen(doSomethingOtherThanThat) :andThen(doSomethingAgain) :catch(print) ``` -------------------------------- ### TweenService Wrapper in Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/Examples.md Illustrates converting Roblox's event-driven TweenService into a promise-based function in Lua for easier async handling. Depends on Promise library and TweenService. Inputs include object, TweenInfo, and properties; outputs a promise resolving on tween completion. Includes cancellation support. ```lua local function tween(obj, tweenInfo, props) return function() return Promise.new(function(resolve, reject, onCancel) local tween = TweenService:Create(obj, tweenInfo, props) if onCancel(function() tween:Cancel() end) then return end tween.Completed:Connect(resolve) tween:Play() end) end end ``` -------------------------------- ### Create an Immediately Resolved Promise in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Shows how to create an instantly resolved Promise using `Promise.resolve`. This is valuable for converting synchronous data into a Promise, useful for consistent API design, especially when dealing with caches or starting promise chains with existing data. ```lua local Promise = require(game.ReplicatedStorage.Promise) local cache = {} local function getCachedData(key) if cache[key] then return Promise.resolve(cache[key]) else return fetchDataFromServer(key):andThen(function(data) cache[key] = data return data end) end end -- Both cached and uncached paths return promises getCachedData("playerStats") :andThen(function(stats) print("Stats:", stats) end) ``` -------------------------------- ### Lua: Promise Get Status Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Demonstrates `getStatus()` which returns the current Promise status without yielding. It provides the current status of the promise (Started, Resolved, Rejected, or Cancelled). ```lua local Promise = require(game.ReplicatedStorage.Promise) local promise = Promise.delay(5):andThen(function()\ return "Done!" end) print(promise:getStatus()) -- Output: Started promise:await() print(promise:getStatus()) -- Output: Resolved ``` -------------------------------- ### IsInGroup Wrapper in Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/Examples.md Shows how to wrap a yielding function into a promise-returning one in Lua, specifically for checking group membership. Requires the Promise library and Roblox Player service. Inputs are a player object and group ID; outputs a promise resolving to a boolean. Promisify is an alternative but not used here. ```lua local function isPlayerInGroup(player, groupId) return Promise.new(function(resolve) resolve(player:IsInGroup(groupId)) end) end ``` -------------------------------- ### Promisify a yielding function - Roblox Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/Tour.md Demonstrates how to convert a function that uses yielding operations (like wait) into a Promise-returning function using Promise.promisify. The example shows calling the promisified function, chaining an andThen handler, and a catch handler for potential rejections. ```lua local function myYieldingFunction(waitTime, text) wait(waitTime) return text end local myFunction = Promise.promisify(myYieldingFunction) myFunction(1.2, "Hello world!"):andThen(print):catch(function() warn("Oh no... goodbye world.") end) ``` -------------------------------- ### Chain Promises with andThen in Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/WhyUsePromises.md Demonstrates how to chain multiple asynchronous functions using the `andThen` method. This ensures that each function executes sequentially, with the next function only starting after the previous one completes. Errors are handled with the `catch` method. ```lua async1() :andThen(async2) :andThen(async3) :andThen(async4) :andThen(async5) :catch(function(err) warn("Oh no! This went wrong somewhere along the line:", err) end) ``` -------------------------------- ### Create HTTP GET Promise in Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/WhyUsePromises.md Wraps Roblox's HttpService:GetAsync in a Promise to handle HTTP requests asynchronously. The function returns a Promise that resolves with the response or rejects with an error. ```lua local HttpService = game:GetService("HttpService") local function httpGet(url) return Promise.new(function(resolve, reject) local ok, result = pcall(HttpService.GetAsync, HttpService, url) if ok then resolve(result) else reject(result) end end) end ``` -------------------------------- ### Defer Promise Execution Until Next Heartbeat in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Illustrates using `Promise.defer` to create a Promise whose executor runs after the next Heartbeat. This is useful for scenarios like waiting for an instance to exist with a timeout, ensuring proper setup before execution. It includes `andThen` for success and `catch` for timeouts or errors. ```lua local Promise = require(game.ReplicatedStorage.Promise) -- Wait for a child to exist with timeout local function waitForChildSafe(instance, childName, timeout) return Promise.defer(function(resolve, reject, onCancel) local child = instance:WaitForChild(childName, timeout) if child then resolve(child) else reject("Timeout waiting for " .. childName) end end) end waitForChildSafe(workspace, "ImportantPart", 5) :andThen(function(part) print("Found part:", part.Name) part.BrickColor = BrickColor.new("Bright red") end) :catch(function(err) warn("Failed to find part:", err) end) ``` -------------------------------- ### Create an Immediately Rejected Promise in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Demonstrates creating an instantly rejected Promise using `Promise.reject`. This is useful for providing immediate error feedback in functions, allowing for early exits in promise chains when certain conditions are not met. ```lua local Promise = require(game.ReplicatedStorage.Promise) local function validateAndProcess(data) if not data then return Promise.reject("Data cannot be nil") end if data.value < 0 then return Promise.reject("Value must be non-negative") end return processData(data) end validateAndProcess({value = -5}) :catch(function(err) warn("Validation failed:", err) -- Output: Validation failed: Value must be non-negative end) ``` -------------------------------- ### Wrap Roblox TweenService with Promises (Lua) Source: https://context7.com/evaera/roblox-lua-promise/llms.txt This snippet demonstrates how to create a Promise‑based wrapper around Roblox's TweenService, allowing asynchronous tween execution with cancellation support. It depends on the Roblox Promise library and the TweenService API, accepting an instance, TweenInfo, and property table, and resolves with the instance on success or rejects on interruption. The implementation also shows chaining multiple tweens using andThen and handling errors with catch. ```text local Promise = require(game.ReplicatedStorage.Promise) local TweenService = game:GetService("TweenService") local function promiseTween(instance, tweenInfo, properties) return Promise.new(function(resolve, reject, onCancel) local tween = TweenService:Create(instance, tweenInfo, properties) -- Handle cancellation if onCancel(function() tween:Cancel() -- Optionally snap to end state for prop, value in pairs(properties) do instance[prop] = value end end) then return -- Already cancelled end local connection connection = tween.Completed:Connect(function(playbackState) connection:Disconnect() if playbackState == Enum.PlaybackState.Completed then resolve(instance) else reject("Tween was interrupted") end end) tweenPlay() end) end -- Use it local part = workspace.TestPart promiseTween( part, TweenInfo.new(2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {Position = Vector3.new(0, 50, 0), Transparency = 0.5} ) :andThen(function() print("Tween completed!") return promiseTween( part, TweenInfo.new(2), {Position = Vector3.new(0, 10, 0), Transparency = 0} ) endn :andThen(function() print("Second tween completed!") end) :catch(function(err) warn("Tween failed:", err) end) ``` -------------------------------- ### Lua: Promise Expect Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Shows how to use `expect()` to yield until a Promise completes and return resolved values, throwing an error if the Promise is rejected or cancelled. Suitable when an operation is expected to succeed. ```lua local Promise = require(game.ReplicatedStorage.Promise) local function loadCriticalData() return Promise.delay(1):andThenReturn({\ config = "important settings",\ version = "1.0"\ }) end -- This will error if the promise rejects local data = loadCriticalData():expect() print("Loaded critical data:", data.config, data.version) ``` -------------------------------- ### Handle First Resolved Promise with `Promise.any` Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Returns a Promise that resolves as soon as any of the input Promises resolve, ignoring any rejections unless all input Promises reject. If all Promises reject, the returned Promise will reject with an aggregate error containing all rejection reasons. This is useful for trying multiple alternative operations and succeeding on the first one that works. ```lua local Promise = require(game.ReplicatedStorage.Promise) local function tryServer(serverId) return Promise.new(function(resolve, reject) Promise.delay(math.random()) :andThen(function() if math.random() > 0.3 then resolve("Connected to server " .. serverId) else reject("Server " .. serverId .. " unavailable") end end) end) end -- Try connecting to multiple servers, succeed on first success Promise.any({ tryServer(1), tryServer(2), tryServer(3), tryServer(4) }) :andThen(function(result) print("Connection successful:", result) end) :catch(function(err) warn("All servers failed:", err) end) ``` -------------------------------- ### Lua: Promise Await Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Demonstrates the `await()` method to yield execution until a Promise completes, returning a boolean success status and the resolved/rejected value. This is useful for integrating asynchronous code with synchronous code. ```lua local Promise = require(game.ReplicatedStorage.Promise) local function getUserScore(userId) return Promise.delay(1):andThenReturn(math.random(100, 1000)) end -- In a regular Lua function that can yield local success, score = getUserScore(123):await() if success then print("User score:", score) else warn("Failed to get score:", score) end ``` -------------------------------- ### Create and Handle a New Promise with Executor in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Demonstrates creating a new Promise using `Promise.new` and an executor function. The executor wraps an asynchronous operation (like `IsInGroup`) and calls `resolve` on success or `reject` on failure. It shows chaining with `andThen` and error handling with `catch`. ```lua local Promise = require(game.ReplicatedStorage.Promise) -- Basic example: wrapping IsInGroup local function isPlayerInGroup(player, groupId) return Promise.new(function(resolve, reject) local success, result = pcall(function() return player:IsInGroup(groupId) end) if success then resolve(result) else reject(result) end end) end isPlayerInGroup(game.Players.LocalPlayer, 123456) :andThen(function(isInGroup) print("Player in group:", isInGroup) end) :catch(function(err) warn("Error checking group:", err) end) ``` -------------------------------- ### Handle Promise Resolution and Rejection in Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/WhyUsePromises.md Demonstrates attaching success and failure callbacks to a Promise using andThen and catch methods. The Promise resolves with the HTTP response or rejects with an error. ```lua local promise = httpGet("https://google.com") promise:andThen(function(body) print("Here's the Google homepage:", body) end) promise:catch(function(err) warn("We failed to get the Google homepage!", err) end) ``` -------------------------------- ### Promisify Callback Functions with `Promise.promisify` Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Wraps a yielding function (like `wait`) into a Promise-based function. This allows asynchronous execution of traditional Roblox yielding APIs within promise chains without blocking the main thread. It takes a callback-style function as input and returns a new function that returns a Promise. ```lua local Promise = require(game.ReplicatedStorage.Promise) local sleep = Promise.promisify(wait) print("Starting...") sleep(2) :andThen(function(actualTime) print("Waited for:", actualTime, "seconds") return sleep(1) end) :andThen(function() print("Done!") end) ``` -------------------------------- ### promise:catch Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Shorthand for attaching a rejection handler to a Promise, allowing for error recovery or logging. ```APIDOC ## promise:catch(failureHandler) ### Description Attaches a handler to be called when the Promise is rejected. Shorthand for `:andThen(nil, failureHandler)`. The handler can return a value to recover from the error. ### Method N/A (Promise method) ### Parameters #### Method Parameters - **failureHandler** (function) - Required - Called when the Promise rejects. ### Example Usage ```lua riskyOperation() :andThen(print) :catch(function(err) warn(err) return defaultValue end) ``` ``` -------------------------------- ### Create a resolved Promise with Promise.resolve - Roblox Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/Tour.md Illustrates creating a Promise that is immediately resolved with a given value. This is useful for wrapping a value in a Promise context without any asynchronous operations. The resolved value is then printed using an andThen handler. ```lua local function myFunction() return Promise.resolve("Hello world!") end myFunction():andThen(print) ``` -------------------------------- ### promise:andThen Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Chains onto an existing Promise, allowing for sequential asynchronous operations with success and failure handlers. ```APIDOC ## promise:andThen(successHandler, failureHandler) ### Description Attaches handlers to be called when the Promise is settled. The success handler is called on resolution, the failure handler on rejection. Both can return values or new Promises for further chaining. ### Method N/A (Promise method) ### Parameters #### Method Parameters - **successHandler** (function) - Optional - Called when the Promise resolves. - **failureHandler** (function) - Optional - Called when the Promise rejects. ### Example Usage ```lua getUserData(123) :andThen(function(user) return getInventory(user.id) end) :andThen(print) :catch(warn) ``` ``` -------------------------------- ### Lua: Promise On Unhandled Rejection Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Shows how to register a global callback using `Promise.onUnhandledRejection(callback)` which fires when a Promise rejects without handlers. Returns a function to unregister the callback. ```lua local Promise = require(game.ReplicatedStorage.Promise) -- Set up global error handler local unregister = Promise.onUnhandledRejection(function(promise, ...) \ local errorMessage = tostring(select(1, ...)) warn("UNHANDLED PROMISE REJECTION:", errorMessage) -- Log to analytics service AnalyticsService:LogError("UnhandledPromise", errorMessage) end) -- This will trigger the handler because there’s no :catch() Promise.reject("Something went wrong!") -- Later, if needed: -- unregister() ``` -------------------------------- ### Lua: Promise Await Status Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Illustrates the `awaitStatus()` method, which returns the Promise's status (Resolved, Rejected, or Cancelled) along with the resolved/rejected value. Offers more explicit status handling compared to `await()`. ```lua local Promise = require(game.ReplicatedStorage.Promise) local function loadAsset(assetId) return Promise.delay(1):andThenReturn({id = assetId, data = "Asset"}) end local promise = loadAsset(123) -- Somewhere else, cancel it task.defer(function() \ wait(0.5) promise:cancel() end) -- Check the final status local status, value = promise:awaitStatus() if status == Promise.Status.Resolved then print("Loaded:", value) elif status == Promise.Status.Rejected then warn("Failed:", value) elif status == Promise.Status.Cancelled then warn("Cancelled!") end ``` -------------------------------- ### Create a Promise from an Event - Roblox Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/Tour.md Shows how to create a Promise that resolves when a specific event fires. It uses Promise.new and connects to an event, resolving the Promise with the event arguments and disconnecting afterward. It also includes an onCancel callback to disconnect the event listener if the Promise is cancelled. ```lua local myFunction() return Promise.new(function(resolve, reject, onCancel) local connection connection = someEvent:Connect(function(...) connection:Disconnect() resolve(...) end) onCancel(function() connection:Disconnect() end) end) end myFunction():andThen(print) ``` -------------------------------- ### Create a Promise with Promise.new - Roblox Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/Tour.md Demonstrates creating a Promise that resolves after a yielding operation. It uses Promise.new with a function that calls somethingThatYields() and then resolves with a string. The resolved value is then passed to an andThen handler. ```lua local function myFunction() return Promise.new(function(resolve, reject, onCancel) somethingThatYields() resolve("Hello world!") end) end myFunction():andThen(print) ``` -------------------------------- ### Handle Multiple Promises with `Promise.all` Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Accepts an array of Promises and returns a new Promise that resolves only when all input Promises have resolved, or rejects immediately if any input Promise rejects. The resolved value is an array containing the resolved values of the input Promises in their original order. This is useful for loading multiple resources concurrently. ```lua local Promise = require(game.ReplicatedStorage.Promise) local HttpService = game:GetService("HttpService") local function httpGet(url) return Promise.new(function(resolve, reject) local ok, result = pcall(HttpService.GetAsync, HttpService, url) if ok then resolve(result) else reject(result) end end) end -- Load multiple resources concurrently Promise.all({ httpGet("https://api.example.com/user/123"), httpGet("https://api.example.com/inventory/123"), httpGet("https://api.example.com/achievements/123"), httpGet("https://api.example.com/friends/123") }) :andThen(function(results) local userData = HttpService:JSONDecode(results[1]) local inventory = HttpService:JSONDecode(results[2]) local achievements = HttpService:JSONDecode(results[3]) local friends = HttpService:JSONDecode(results[4]) print("All data loaded successfully!") return { user = userData, inventory = inventory, achievements = achievements, friends = friends } end) :catch(function(err) warn("Failed to load all data:", err) end) ``` -------------------------------- ### Immediately resolve or reject using now (Lua) Source: https://context7.com/evaera/roblox-lua-promise/llms.txt now checks whether the promise is already resolved; if so it resolves instantly, otherwise it rejects. This method is useful for quickly accessing cached data without waiting for asynchronous loading, falling back to alternative flows when data is unavailable. ```Lua local Promise = require(game.ReplicatedStorage.Promise) local cache = {} local function getCachedUser(userId) if cache[userId] then return Promise.resolve(cache[userId]) else return fetchUserData(userId):andThen(function(data) cache[userId] = data return data end) end end -- Try to get immediately, fall back to loading screen if not cached getCachedUser(123) :now() :andThen(function(userData) print("Got cached data immediately:", userData) end) :catch(function() print("Not cached, showing loading screen...") return getCachedUser(123) -- Actually wait this time end) ``` -------------------------------- ### Executing a function asynchronously with Promise.try - Roblox Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/Tour.md Introduces Promise.try as a convenient way to run a function asynchronously, similar to spawn but integrated with the Promise system. It allows other code to run concurrently without being blocked by the yielded operations within the try function. ```lua Promise.try(function() somethingThatYields() end) -- Doesn't block this someCode() ``` -------------------------------- ### Handle First Settled Promise with `Promise.race` Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Returns a Promise that settles (resolves or rejects) as soon as any of the input Promises settle. The returned Promise will have the same settlement value (either resolved value or rejection reason) as the first Promise to settle. This is useful for scenarios where you need the fastest response from multiple sources. ```lua local Promise = require(game.ReplicatedStorage.Promise) local function fetchFromPrimary() return Promise.delay(2):andThenReturn("Primary server data") end local function fetchFromBackup() return Promise.delay(1):andThenReturn("Backup server data") end local function fetchFromCache() return Promise.delay(0.5):andThenReturn("Cached data") end -- Get data from whichever source responds first Promise.race({ fetchFromPrimary(), fetchFromBackup(), fetchFromCache() }) :andThen(function(data) print("First response:", data) -- Output: First response: Cached data end) ``` -------------------------------- ### Run Promises Concurrently with Promise.all in Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/WhyUsePromises.md Illustrates how to run multiple promises concurrently using `Promise.all`. The resulting promise resolves with an array of resolved values, and rejects if any of the input promises reject. ```lua Promise.all({ async1(), async2(), async3(), async4() }):andThen(function(arrayOfResolvedValues) print("Done running all 4 functions!") end):catch(function(err) warn("Uh oh, one of the Promises rejected! Abort mission!") end) ``` -------------------------------- ### Handle Promise Rejections with catch in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Attaches a failure handler to a Promise chain as a shorthand for andThen with nil success handler. Allows error recovery by returning values or new Promises. Depends on Promise module; inputs are the Promise and failure handler; outputs a new Promise that can continue the chain post-recovery. ```lua local Promise = require(game.ReplicatedStorage.Promise) local function riskyOperation() return Promise.new(function(resolve, reject) if math.random() > 0.5 then resolve("Success!") else reject("Operation failed") end end) end riskyOperation() :andThen(function(result) print("Result:", result) end) :catch(function(err) warn("Caught error:", err) -- Could return a value here to recover from the error return "Recovered with default value" end) :andThen(function(value) print("Final value:", value) -- This runs whether we succeeded or recovered from error end) ``` -------------------------------- ### Lua: Promise Error Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Explains `Promise.Error` which is an error object designed for enhanced debugging with error chains, context, and stack traces. Provides methods for checking and extending error types. ```lua local Promise = require(game.ReplicatedStorage.Promise) local function loadUserData(userId) return Promise.new(function(resolve, reject) \ if userId < 0 then reject(Promise.Error.new({\ error = "Invalid user ID",\ kind = Promise.Error.Kind.ExecutionError,\ context = "User ID must be positive: " .. tostring(userId) })) else resolve({id = userId, name = "Player" .. userId}) end end) end loadUserData(-5) :andThen(function(data) \ print("Loaded:", data) end) :catch(function(err) \ if Promise.Error.is(err) then\ print("Error kind:", err.error) print("Context:", err.context) print("Trace:", err.trace) else\ warn("Regular error:", tostring(err)) end end) ``` -------------------------------- ### Invoke callback with predefined arguments using andThenCall (Lua) Source: https://context7.com/evaera/roblox-lua-promise/llms.txt andThenCall attaches an andThen handler that calls a specified callback with preset arguments followed by the resolved value. This is handy for partially applying functions within a promise chain. The original promise flow continues after the callback execution. ```Lua local Promise = require(game.ReplicatedStorage) local function grantItem(player, itemName, quantity) print("Granting", quantity, itemName, "to", player.Name) end local function getPlayerReward(playerId) return Promise.delay(0.5):andThenReturn("Gems") end local player game.Players.LocalPlayer getPlayerReward(player.UserId) :andThenCall(grantItem, player,Gems", 100) :andThen(function() print("Reward granted successfully!") end) ``` -------------------------------- ### Creating a delayed Promise with Promise.delay - Roblox Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/Tour.md Shows how to use Promise.delay to create a Promise that resolves after a specified number of seconds. This is presented as a more reliable alternative to Roblox's wait() function for managing asynchronous delays. ```lua Promise.delay(5):andThen(function() print("5 seconds have passed!") end) ``` -------------------------------- ### Promise.retryWithDelay Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Retries a callback function a specified number of times with a delay between attempts, useful for implementing backoff strategies or handling rate limits. ```APIDOC ## Promise.retryWithDelay(callback, times, seconds, ...args) ### Description Retries a callback function up to a specified number of times with a delay between each attempt. Useful for operations that may fail temporarily, such as network requests or database queries. ### Method N/A (Library function) ### Parameters #### Function Parameters - **callback** (function) - Required - The function to retry. Should return a Promise. - **times** (number) - Required - Maximum number of retry attempts. - **seconds** (number) - Required - Delay in seconds between attempts. - **...args** (any) - Optional - Additional arguments to pass to the callback. ### Example Usage ```lua Promise.retryWithDelay(function() return flakeyDatabaseQuery(12345) end, 3, 2) :andThen(print) :catch(warn) ``` ``` -------------------------------- ### Promise.fromEvent Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Converts a Roblox event into a Promise that resolves the next time the event fires, optionally filtered by a predicate function. ```APIDOC ## Promise.fromEvent(event, predicate) ### Description Creates a Promise that resolves the next time a specified Roblox event fires. An optional predicate function can filter which event firings should resolve the Promise. ### Method N/A (Library function) ### Parameters #### Function Parameters - **event** (RBXScriptSignal) - Required - The Roblox event to listen to. - **predicate** (function) - Optional - A function that filters event firings. Should return true to resolve the Promise. ### Example Usage ```lua Promise.fromEvent(part.Touched, function(otherPart) return game.Players:GetPlayerFromCharacter(otherPart.Parent) end) :andThen(print) :catch(warn) ``` ``` -------------------------------- ### Execute Callback Safely within a Promise Chain in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Explains how to use `Promise.try` to safely execute a callback function and wrap its result in a Promise. If the callback throws an error, `Promise.try` automatically returns a rejected Promise, simplifying error handling for synchronous code integrated into asynchronous flows. ```lua local Promise = require(game.ReplicatedStorage.Promise) Promise.try(function() local value = math.random(1, 2) if value == 1 then return "Success!" else error("Random failure occurred") end end) :andThen(function(result) print("Got result:", result) end) :catch(function(err) warn("Operation failed:", err) end) ``` -------------------------------- ### Execute Cleanup with finally in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Runs a handler after a Promise settles, regardless of resolution, rejection, or cancellation, receiving the status. Useful for cleanup like hiding UI elements. Requires Promise module; inputs are the Promise and finally handler; does not alter the Promise outcome but ensures side effects. ```lua local Promise = require(game.ReplicatedStorage.Promise) local gui = script.Parent.LoadingScreen gui.Visible = true loadGameData() :andThen(function(data) print("Data loaded:", data) initializeGame(data) end) :catch(function(err) warn("Failed to load:", err) showErrorScreen() end) :finally(function(status) -- Always hide loading screen regardless of outcome gui.Visible = false print("Loading complete with status:", status) end) ``` -------------------------------- ### Chaining Promises with andThen - Roblox Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/Tour.md Shows how to chain multiple asynchronous operations using the andThen method. Each andThen call returns a new Promise that resolves with the return value of its handler, allowing for sequential execution of operations. ```lua somePromise:andThen(function(number) return number + 1 end):andThen(print) ``` -------------------------------- ### Retry Promise with Delay in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Retries a callback function up to a specified number of times with a delay between attempts, ideal for backoff or rate limiting. Requires the Promise module from ReplicatedStorage. Inputs include the callback, retry count, delay in seconds, and additional arguments; outputs a new Promise that resolves if successful or rejects after all attempts fail. ```lua local Promise = require(game.ReplicatedStorage.Promise) local attemptCount = 0 local function flakeyDatabaseQuery(userId) attemptCount = attemptCount + 1 print("Query attempt", attemptCount, "for user", userId) return Promise.new(function(resolve, reject) if math.random() > 0.6 then resolve({id = userId, name = "Player" .. userId, coins = 1000}) else reject("Database timeout") end end) end -- Retry up to 3 times with 2 second delay between attempts Promise.retryWithDelay(function() return flakeyDatabaseQuery(12345) end, 3, 2) :andThen(function(userData) print("User data retrieved:", userData.name, userData.coins, "coins") end) :catch(function(err) warn("All retries failed:", err) end) ``` -------------------------------- ### Promisify a yielding function with Roblox Lua Promise Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/WhyUsePromises.md Shows how to convert a yielding function into a Promise-returning function with `Promise.promisify` in Roblox Lua. After promisifying `myFunctionAsync`, the resulting function can be called and chained with `andThen` and `catch` for asynchronous handling. Requires the Promise library; the original function must be a coroutine that yields. ```Lua -- Assuming myFunctionAsync is a function that yields. local myFunction = Promise.promisify(myFunctionAsync) myFunction("some", "arguments"):andThen(print):catch(warn) ``` -------------------------------- ### Chain Promises in Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/WhyUsePromises.md Shows how to chain Promises where the resolution of one Promise triggers another HTTP request. The final catch handles errors from any point in the chain. ```lua httpGet("https://google.com") :andThen(function(body) return httpGet("https://eryn.io") end) :andThen(function(body) print("Here's the eryn.io homepage:", body) end) :catch(warn) ``` -------------------------------- ### Chain Promises with andThen in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Chains success and failure handlers onto an existing Promise, returning a new Promise. Handlers can return values or Promises for further chaining. Requires the Promise module; inputs are the prior Promise and handlers; outputs a new Promise propagating the result. ```lua local Promise = require(game.ReplicatedStorage.Promise) local function getUserData(userId) return Promise.delay(0.5):andThenReturn({ id = userId, name = "Player" .. userId, level = 10 }) end getUserData(123) :andThen(function(userData) print("Got user:", userData.name) -- Return a new Promise to chain return Promise.delay(0.5):andThenReturn({ userId = userData.id, inventory = {"Sword", "Shield", "Potion"} }) end) :andThen(function(inventory) print("Got inventory:", table.concat(inventory.inventory, ", ")) return inventory end) :catch(function(err) warn("Error in chain:", err) end) ``` -------------------------------- ### Create Delays with `Promise.delay` Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Returns a Promise that resolves after a specified number of seconds. This method is more reliable than `wait()` as it utilizes the Promise scheduler for more accurate timing. It resolves with the actual time elapsed. Chaining multiple delays is also demonstrated. ```lua local Promise = require(game.ReplicatedStorage.Promise) print("Starting countdown...") Promise.delay(5) :andThen(function(actualTime) print("5 seconds elapsed! (actual:", actualTime, ")") end) -- Chaining delays Promise.delay(1) :andThen(function() print("1 second") return Promise.delay(1) end) :andThen(function() print("2 seconds") return Promise.delay(1) end) :andThen(function() print("3 seconds") end) ``` -------------------------------- ### Lua: Promise Is Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Explains `Promise.is(object)` which checks if an object is a Promise using duck typing. Useful for handling values that may or may not be Promises. ```lua local Promise = require(game.ReplicatedStorage.Promise) local function handleValue(value) if Promise.is(value) then print("It's a Promise!") return value:andThen(function(resolved) \ print("Promise resolved to:", resolved) return resolved end) else print("It’s a regular value:", value) return Promise.resolve(value) end end handleValue(42) -- Regular value handleValue(Promise.delay(1):andThenReturn(100)) -- Promise ``` -------------------------------- ### promise:finally Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Attaches a handler that runs regardless of the Promise's outcome, useful for cleanup operations. ```APIDOC ## promise:finally(finallyHandler) ### Description Attaches a handler that is called when the Promise settles, regardless of resolution, rejection, or cancellation. Useful for cleanup operations that must run in all cases. ### Method N/A (Promise method) ### Parameters #### Method Parameters - **finallyHandler** (function) - Required - Called when the Promise settles. ### Example Usage ```lua loadGameData() :andThen(initializeGame) :catch(showError) :finally(function() loadingScreen.Visible = false end) ``` ``` -------------------------------- ### Replace resolved value with specified values using andThenReturn (Lua) Source: https://context7.com/evaera/roblox-lua-promise/llms.txt andThenReturn ignores the previous resolved value and returns the provided arguments instead, allowing you to substitute data in a promise chain. Useful for simplifying downstream handlers when the original result is no longer needed. ```Lua local Promise = require(game.ReplicatedStorage.Promise) Promise.delay(2) :andThen(function(elapsed) print("Waited for:", elapsed) end) :andThenReturn("New value", 123, true) :andThen(function(str, num, bool) print(str, num, bool) -- Output: New value 123 true end) ``` -------------------------------- ### Cancel a Promise and Attach an OnCancel Hook in Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/WhyUsePromises.md Demonstrates how to cancel a promise and attach an `onCancel` hook to execute cleanup code when the promise is cancelled. This is useful for stopping ongoing operations or releasing resources. ```lua local function tween(obj, tweenInfo, props) return Promise.new(function(resolve, reject, onCancel) local tween = TweenService:Create(obj, tweenInfo, props) -- Register a callback to be called if the Promise is cancelled. onCancel(function()\t tween:Cancel() end) tween.Completed:Connect(resolve) tween:Play() end) ``` -------------------------------- ### Use await to Safely Yield for Promise Results in Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/WhyUsePromises.md Shows how to use the `await` method to safely wait for the result of a promise within another promise. This is similar to the `await` keyword in JavaScript and allows the outer Promise to resolve once the inner Promise completes. ```lua local function async1() return Promise.new(function(resolve, reject) local ok, value = async2():await() if not ok then return reject(value) end resolve(value + 1) end) ``` -------------------------------- ### Convert Roblox Event to Promise in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Transforms a Roblox event into a Promise that resolves when the event fires, with an optional predicate to filter events. Depends on the Promise module. Inputs are the event object and optional filter function; outputs a Promise that resolves with event arguments or rejects on timeout if specified. ```lua local Promise = require(game.ReplicatedStorage.Promise) local part = workspace.TouchPart -- Wait for a specific player to touch the part Promise.fromEvent(part.Touched, function(otherPart) local player = game.Players:GetPlayerFromCharacter(otherPart.Parent) return player and player.Name == "TargetPlayer" end) :andThen(function(touchedPart) print("TargetPlayer touched the part!") part.BrickColor = BrickColor.new("Bright green") end) :timeout(10) :catch(function(err) warn("Target player didn't touch part in time:", err) end) ``` -------------------------------- ### Retry Promise.retry Function in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Promise.retry repeatedly calls a Promise-returning function up to a specified number of times until it resolves. Depends on the Roblox Promise library. Takes a callback function, number of attempts, and optional args, outputs the resolved value or last rejection. Limitations include fixed retry count; may not handle varying error types. ```lua local Promise = require(game.ReplicatedStorage.Promise) local HttpService = game:GetService("HttpService") local attemptCount = 0 local function unreliableRequest() attemptCount = attemptCount + 1 print("Attempt", attemptCount) return Promise.new(function(resolve, reject) -- Simulate unreliable network if math.random() > 0.7 then resolve("Request successful!") else reject("Network error") end end) end Promise.retry(unreliableRequest, 5) :andThen(function(result) print(result) print("Succeeded after", attemptCount, "attempts") end) :catch(function(err) warn("Failed after 5 attempts:", err) end) ``` -------------------------------- ### Iterate Promise.each Serially in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Promise.each iterates serially over an array, calling a predicate on each value that can return a Promise. Depends on the Roblox Promise library. Takes an array and a predicate function, outputs an array of results. Limitations include sequential execution, which may be slower for parallel operations. ```lua local Promise = require(game.ReplicatedStorage.Promise) local players = {"Alice", "Bob", "Charlie", "David"} Promise.each(players, function(playerName, index) return Promise.delay(1):andThen(function() print(index, ") Processing player:", playerName) -- Simulate some async work return { name = playerName, processed = true, timestamp = os.time() } end) end) :andThen(function(results) print("All players processed sequentially!") for i, result in ipairs(results) do print(result.name, "processed at", result.timestamp) end end) ``` -------------------------------- ### Resolve Promise.some with Count in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Promise.some returns a Promise that resolves when the specified count of input promises have resolved, rejecting if it becomes impossible to reach that count. Depends on the Roblox Promise library. Takes an array of promises and a count number, outputs an array of the resolved values from the fastest promises. Limitations include requiring at least the specified count to resolve successfully. ```lua local Promise = require(game.ReplicatedStorage.Promise) local function pingServer(serverId, delay) return Promise.delay(delay):andThenReturn({ id = serverId, latency = delay * 1000 }) end -- Find the 2 fastest servers Promise.some({ pingServer(1, 0.5), pingServer(2, 0.2), pingServer(3, 0.8), pingServer(4, 0.3), pingServer(5, 0.6) }, 2) :andThen(function(fastestServers) print("Two fastest servers:") for _, server in ipairs(fastestServers) do print("Server", server.id, "- Latency:", server.latency, "ms") end -- Output will show servers 2 and 4 (lowest delays) end) ``` -------------------------------- ### Adding a timeout to a Promise with Promise:timeout - Roblox Lua Source: https://github.com/evaera/roblox-lua-promise/blob/master/docs/Tour.md Explains the use of the Promise:timeout method, which rejects a Promise if it does not resolve within a specified time limit. This is useful for preventing operations from hanging indefinitely and ensuring timely responses. ```lua returnsAPromise():timeout(5):andThen(function() print("This returned in at most 5 seconds") end) ``` -------------------------------- ### Fold Promise.fold Sequentially in Lua Source: https://context7.com/evaera/roblox-lua-promise/llms.txt Promise.fold folds an array sequentially using a reducer function that can return a Promise. Depends on the Roblox Promise library. Takes an array, reducer function, and initial value, outputs the final accumulated value. Limitations include sequential processing, ensuring order but potentially slower. ```lua local Promise = require(game.ReplicatedStorage.Promise) local fruits = {"apple", "banana", "cherry", "date"} local prices = { apple = 1.50, banana = 0.75, cherry = 2.00, date = 3.00 } local function fetchPrice(fruitName) return Promise.delay(0.5):andThenReturn(prices[fruitName]) end -- Calculate total cost sequentially Promise.fold(fruits, function(totalCost, fruit, index) return fetchPrice(fruit):andThen(function(price) print(index, ")", fruit, "-", price) return totalCost + price end) end, 0) :andThen(function(total) print("Total cost:", total) -- Output: Total cost: 7.25 end) ``` -------------------------------- ### Cancel Promise and clean up with cancel (Lua) Source: https://context7.com/evaera/roblox-lua-promise/llms.txt The cancel method stops a promise from resolving or rejecting and propagates cancellation through the chain. By registering onCancel callbacks, you can release resources such as tweens or network requests, ensuring proper cleanup when an operation is aborted. ```Lua local Promise = require(game.ReplicatedStorage.Promise) local TweenService = game:GetService("TweenService") local function animatePart(part, targetCFrame) return Promise.new(function(resolve, reject, onCancel) local tween = TweenService:Create( part, TweenInfo.new(5), {CFrame = targetCFrame} ) -- Register cleanup onCancel(function() tween:Cancel() print("Animation cancelled!") end) tween.Completed:Connect(resolve) tween:Play() end) end local animation = animatePart( workspace.Part, CFrame.new(0, 100, 0) ) -- Cancel after 2 seconds wait(2) animation:cancel() ```