Skip to content

Async

local Async = require("@game/ReplicatedStorage/Twill").Async
local finished, code = Async.Timeout(10, TeleportService.ReserveServerAsync, TeleportService, placeId)
local fetched, body = Async.Retry(HttpService.GetAsync, { Attempts = 3 }, HttpService, url)

Every function yields the calling thread and returns plain values, in the shape pcall uses: true and the results, or false and a reason. Nothing is chained and nothing has to be awaited later.

A reason is the error the call raised, or one of two values on the module:

ValueMeaning
Async.TimedOutThe deadline passed before the call finished.
Async.CancelledThe owner bag of a retry closed.

Timeout and All run each call on its own thread and cancel it where it stands when the deadline passes. Work that must never stop halfway, such as a save or a grant, does not belong in them.

Retry runs on the calling thread and never cuts a call off. It only decides whether to make another.

[Server] | [Client]

Runs a call and waits for it, but no longer than a deadline.

function Async.Timeout(seconds: number, callback: (...any) -> ...any, ...: any): (boolean, ...any)

Parameters

NameTypeDescription
secondsnumberThe longest to wait. Zero or more.
callback(...any) -> ...anyWhat to run.
...anyWhat to run it with.

Returns

boolean - true when the call finished in time without raising.

...any - What the call returned, or the error it raised, or Async.TimedOut.

Yields. Throws on a duration that is negative, infinite or not a number, and on a callback that is not a function.

[Server] | [Client]

Runs several calls at once and waits for every one, or for a deadline.

function Async.All(callbacks: { () -> ...any }, seconds: number?): (boolean, { Outcome })

Parameters

NameTypeDescription
callbacks{ () -> ...any }The calls to run. Each takes no arguments.
secondsnumber?The longest to wait for all of them. 30 when left out.

Returns

boolean - true when every call finished in time without raising.

{ Outcome } - One entry per call, in order, holding what pcall would have returned, with n set. A call cut off by the deadline holds false and Async.TimedOut.

Yields. An empty list returns true at once. Throws on a list that holds anything but functions.

[Server] | [Client]

Runs a call on the calling thread, and tries it again when it raises.

function Async.Retry(callback: (...any) -> ...any, options: RetryOptions?, ...: any): (boolean, ...any)

Parameters

NameTypeDescription
callback(...any) -> ...anyWhat to run.
optionsRetryOptions?How many tries, how long between them, and when to stop.
...anyWhat to run it with.

Returns

boolean - true when a try went through.

...any - What that try returned, or the last error, or Async.Cancelled.

Yields. Throws on a callback that is not a function, and on options out of range.

Each wait is longer than the one before and spread at random between half and all of its length, so many servers retrying together do not return together.

FieldDefaultMeaning
Attempts3Tries in total. A whole number of at least one.
Delay1Seconds before the second try.
Growth2What each wait is multiplied by. At least one.
Ceiling30The longest wait. No less than Delay.
ShouldRetrynone(message: string) -> boolean. Stops at once when it answers anything but true, or raises.
OwnernoneA bag. Once it closes, no further try is made.
LimitValue
Default deadline for All30 seconds
Default tries for Retry3
Default longest wait between tries30 seconds