Skip to main content

Observable

Observables are objects that resolve to some value, and can be subscribed to detect updates whenver this value changes.

When setting a VirtualInstance's properties to an Observable, the properties in the mounted instance will automatically be updated by Dex to match the current value of the observable whenever its value changes.

An observable will automatically be garbage collected so long as there are no listeners are currently subscribed to it, and it is not currently being used by a mounted VirtualInstance.

Constructor


Observable is just the base class for a number of available subclasses, such as State, Stopwatch, Dict, [Alpha], etc.

Using Custom Observables should only be done with caution

Dex.CustomObservable

Dex.CustomObservable<T>(
    getCurrent: () -> T,
    createUpdateStream: (notifyChange: () -> ()) -> (() -> ())
) -> Observable<T>

See: Dex.CustomObservable for full documentation

CAUTION

Read the full Dex.CustomObservable documentation before writing Custom Observables; otherwise, opt for other subclasses such as State.

Types

CanBeObservable<T>

type CanBeObservable<T> = Observable<T> | T

Utility type that denotes a value can be an observable. Dex also provides the utility function Dex.CoerceAsObservable for unwrapping these objects.

Functions

Current

Observable:Current() → T

Returns the current value of the Observable.

Map

Observable:Map(mappingFunction(valueT) → any) → Observable<any>

Creates a new Observable that derives its value from this Observable, using a mapping function in the domain of this Observable's value

Example of mapping a number to a currency display value:

local money = Dex.State(3)

local moneyFormatted = money:Map(function(currentMoney)
    return string.format("$%0.2f", currentMoney)
end)

print(moneyFormatted:Current()) -- $3.00

Subscribe

Observable:Subscribe(
listener(valueT) → (),
immediatelyCallListenerboolean?
) → () → ()

Subscribes to changes in the Observable. Returns a function that, when called, will unsubscribe the listener from the Observable's changes. If true is provided as a second argument, will also call the listener once immediately with the current value of the Observable.

CAUTION

Make sure you handle the returned "Unsubscribe" function whenever a calling Subscribe! If you forget to do this, you may encounter memory leaks!

Observables will remain in memory until all listeners are unsubscribed, and all VirtualInstances using it are unmounted

-- A new Observable can always be garbage collected if dereferenced
local coins = createCoinsObserver()

-- However, once we subscribe to it, it will stick
-- around in memory until we call Unsubscribe!
local unsubscribe = coins:Subscribe(function(value)
    print("Coins is", value)
end, true)
task.wait(5)

-- The "coins" observable can now be garbage collected
unsubscribe() 

Destroy

Observable:Destroy() → ()

Destroys the Observable, releasing all its resources and unsubscribing all listeners. All further Observable:Subscribe calls will error.

Show raw api
{
    "functions": [
        {
            "name": "Current",
            "desc": "Returns the current value of the Observable.",
            "params": [],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "T"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 111,
                "path": "src/Observables/Observable.luau"
            }
        },
        {
            "name": "Map",
            "desc": "Creates a new Observable that derives its value from this Observable, using\na mapping function in the domain of this Observable's value\n\nExample of mapping a number to a currency display value:\n```lua\nlocal money = Dex.State(3)\n\nlocal moneyFormatted = money:Map(function(currentMoney)\n    return string.format(\"$%0.2f\", currentMoney)\nend)\n\nprint(moneyFormatted:Current()) -- $3.00\n```",
            "params": [
                {
                    "name": "mappingFunction",
                    "desc": "",
                    "lua_type": "(value: T) -> any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<any>"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 139,
                "path": "src/Observables/Observable.luau"
            }
        },
        {
            "name": "Subscribe",
            "desc": "Subscribes to changes in the Observable. Returns a function that, when\ncalled, will unsubscribe the listener from the Observable's changes. If\n`true` is provided as a second argument, will also call the listener once\nimmediately with the current value of the Observable.\n\n:::caution\nMake sure you handle the returned \"Unsubscribe\" function whenever a calling\n`Subscribe`! If you forget to do this, you may encounter memory leaks!\n\nObservables will remain in memory until all listeners are unsubscribed, and\nall VirtualInstances using it are unmounted\n```lua\n-- A new Observable can always be garbage collected if dereferenced\nlocal coins = createCoinsObserver()\n\n-- However, once we subscribe to it, it will stick\n-- around in memory until we call Unsubscribe!\nlocal unsubscribe = coins:Subscribe(function(value)\n    print(\"Coins is\", value)\nend, true)\ntask.wait(5)\n\n-- The \"coins\" observable can now be garbage collected\nunsubscribe() \n```\n:::",
            "params": [
                {
                    "name": "listener",
                    "desc": "",
                    "lua_type": "(value: T) -> ()"
                },
                {
                    "name": "immediatelyCallListener",
                    "desc": "",
                    "lua_type": "boolean?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "() -> ()"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 183,
                "path": "src/Observables/Observable.luau"
            }
        },
        {
            "name": "Destroy",
            "desc": "Destroys the Observable, releasing all its resources and unsubscribing all\nlisteners. All further [Observable:Subscribe] calls will error.",
            "params": [],
            "returns": [],
            "function_type": "method",
            "source": {
                "line": 218,
                "path": "src/Observables/Observable.luau"
            }
        }
    ],
    "properties": [],
    "types": [
        {
            "name": "CanBeObservable<T>",
            "desc": "Utility type that denotes a value can be an observable. Dex also provides\nthe utility function [Dex.CoerceAsObservable] for unwrapping these objects.",
            "lua_type": "Observable<T> | T",
            "source": {
                "line": 15,
                "path": "src/Observables/Observable.luau"
            }
        }
    ],
    "name": "Observable",
    "desc": "Observables are objects that resolve to some value, and can be subscribed to\ndetect updates whenver this value changes.\n\nWhen setting a [VirtualInstance]'s properties to an Observable, the\nproperties in the mounted instance will automatically be updated by Dex to\nmatch the current value of the observable whenever its value changes.\n\nAn observable will automatically be garbage collected so long as there are\nno listeners are currently subscribed to it, and it is not currently being\nused by a mounted VirtualInstance.\n\n## Constructor\n\n---\n\nObservable is just the base class for a number of available subclasses, such\nas [State], [Stopwatch], [Dict], [Alpha], etc.\n\nUsing Custom Observables should only be done with caution\n\n### Dex.CustomObservable\n\n```ts\nDex.CustomObservable<T>(\n    getCurrent: () -> T,\n    createUpdateStream: (notifyChange: () -> ()) -> (() -> ())\n) -> Observable<T>\n```\n\n#### See: [Dex.CustomObservable] for full documentation\n\n:::caution\nRead the full [Dex.CustomObservable] documentation before writing Custom\nObservables; otherwise, opt for other subclasses such as [State].\n:::",
    "source": {
        "line": 55,
        "path": "src/Observables/Observable.luau"
    }
}