Skip to content

SFUtils_CallLater

Shadowfen edited this page Jul 30, 2026 · 2 revisions

SFUtils.CallLater is a lightweight timer utility that extends the native zo_callLater API with a higher-level object-oriented interface.

It supports:

  • One-shot timers
  • Periodic timers
  • Automatic retry on callback failure
  • Callback argument passing
  • Safe callback execution through LibSFUtils.safeCall
  • Runtime timer management (start, cancel, destroy)

Object lifecycle

A simple diagram to display normal callback behaviour.

New()
   │
   ▼
Start()
   │
   ▼
Running
   │
   ├── callback succeeds
   │         │
   │         ▼
   │      Complete
   │
   ├── callback fails
   │         │
   │         ▼
   │      Retry
   │
   └── Cancel()
             │
             ▼
        Destroyed

API Summary

Constructors Comparison

Constructor One-shot Periodic Retries Arguments
New()
NewSingle()
NewMaxTries()
NewTimer()

Choosing the Right Constructor

You want... Use
Run once New()
Run once with retries NewMaxTries()
Repeat forever NewTimer()
Alias for compatibility NewSingle()

Configuration Methods

Method Description
SetCallback() Replaces the callback.
SetDelay() Changes the default delay.

Control Methods

Method Description
Start() Starts the timer.
StartWithArgs() Starts with callback arguments.
Cancel() Stops and cleans up the timer. (Cannot be restarted!)
Destroy() Alias for Cancel(), returns nil.
SetCallback() Replaces the callback.
SetDelay() Changes the default delay.

State Methods

Method Description
IsRunning() Returns whether the timer is active.

Creating Timers

One-Shot Timer

Creates a timer that executes once.

local timer = SF.CallLater:New(function()
    d("Executed")
end, 1000)

timer:Start()

Syntax

CallLater:New(callback, delayMs)

Parameters

Parameter Type Description
callback function Function to execute.
delayMs number Delay in milliseconds before execution. Default is 0.

Returns

A new CallLater timer object.


NewSingle()

NewSingle() is simply an alias for New().

local timer = SF.CallLater:NewSingle(callback, 500)

Timer With Retry Support

Creates a one-shot timer that automatically retries if the callback throws an error.

local timer = SF.CallLater:NewMaxTries(function()
    error("Failure")
end, 1000, 3)

timer:Start()

Syntax

CallLater:NewMaxTries(callback, delayMs, maxTries)

Parameters

Parameter Type Description
callback function Function to execute.
delayMs number Delay between attempts.
maxTries number Maximum number of attempts to make.

Notes

  • Retries only occur when the callback throws an error.
  • Successful execution clears retry tracking.
  • maxTries count includes the initial execution attempt.

Periodic Timer

Creates a timer that repeats indefinitely until cancelled.

local timer = SF.CallLater:NewTimer(function()
    d("Tick")
end, 1000)

timer:Start()

Syntax

CallLater:NewTimer(callback, intervalMs)

Parameters

Parameter Type Description
callback function Function called every interval.
intervalMs number Interval in milliseconds.

Starting Timers

Start()

Starts a timer.

timer:Start()

Optionally override the default delay.

timer:Start(500)

Syntax

timer:Start(delayMs)

Parameters

Parameter Type Description
delayMs number Optional delay override for one-shot timers.

Behavior

For one-shot timers:

  • Cancels any currently running instance.
  • Starts a new delayed callback.

For periodic timers:

  • Begins the recurring timer loop.

Returns the timer instance to allow chaining.


StartWithArgs()

Starts a one-shot timer while supplying arguments to the callback.

local timer = SF.CallLater:New(function(name, score)
    d(string.format("%s scored %d", name, score))
end, 1000)

timer:StartWithArgs("Lumo", 9000)

Syntax

timer:StartWithArgs(...)

Notes

  • Only available for one-shot timers.
  • Arguments are stored until execution.
  • Calling this on a periodic timer logs a warning.

Managing Timers

Cancel()

Stops a running timer. After cancellation the timer object cannot simply be restarted; create a new timer or assign a new callback before reuse.

timer:Cancel()

Returns

  • true if the timer was cancelled.
  • false if it was not running.

Effects

Cancelling also clears:

  • callback
  • pending arguments
  • retry information
  • periodic callback
  • interval
  • timer handle

After cancellation the timer object cannot simply be restarted; create a new timer or assign a new callback before reuse.


Destroy()

Alias for Cancel().

timer = timer:Destroy()

Returns nil, making cleanup convenient.


Querying State

IsRunning()

Returns whether the timer is currently active.

if timer:IsRunning() then
    d("Still running")
end

Returns

true

or

false

Modifying Timers

SetCallback()

Replaces the callback.

timer:SetCallback(function()
    d("New callback")
end)

Syntax

timer:SetCallback(callback)

Returns the timer instance.


SetDelay()

Changes the default delay used by one-shot timers.

timer:SetDelay(2000)

Syntax

timer:SetDelay(delayMs)

Changing the delay does not affect a currently running timer. The new delay is used the next time Start() is called.

Returns the timer instance.


Error Handling

All callbacks execute through:

LibSFUtils.safeCall()

This prevents Lua errors from propagating into the addon.

One-Shot Timers

If the callback fails:

  • retry counter increments
  • timer is rescheduled if retries remain
  • retry tracking is cleared once exhausted

Periodic Timers

If the callback fails:

  • error is logged
  • next interval continues normally

The periodic timer is not cancelled by callback errors.


Method Chaining

Most methods return the timer instance.

local timer =
    SF.CallLater:New(callback, 1000)
        :SetDelay(500)
        :Start()

Typical Usage

Execute Once

SF.CallLater:New(function()
    d("Finished")
end, 2000):Start()

Delayed Function With Arguments

SF.CallLater:New(function(player, gold)
    d(player .. " has " .. gold)
end, 500):StartWithArgs("@Player", 25000)

Try Until Success

local timer = SF.CallLater:NewMaxTries(function()
    assert(IsPlayerActivated())
end, 1000, 5)

timer:Start()

Heartbeat Timer

local heartbeat = SF.CallLater:NewTimer(function()
    d("Heartbeat")
end, 1000)

heartbeat:Start()

Later:

heartbeat:Cancel()

Implementation Notes

  • One-shot timers use the native zo_callLater.
  • Periodic timers are implemented by rescheduling themselves after each execution.
  • All secure callback execution is protected by LibSFUtils.safeCall.
  • Retry logic is available only for one-shot timers.
  • StartWithArgs() is supported only for one-shot timers.
  • Timer objects maintain their own execution state, making multiple concurrent timers independent of one another.

Clone this wiki locally