Skip to main content

Observable

Observables are like an signal, except they do not execute code until the observable is subscribed to. This follows the standard Rx API surface for an observable.

Observables use a Subscription to emit values.

-- Constucts an observable which will emit a, b, c via a subscription
local observable = Observable.new(function(sub)
	print("Connected")
	sub:Fire("a")
	sub:Fire("b")
	sub:Fire("c")
	sub:Complete() -- ends stream
end)

local sub1 = observable:Subscribe() --> Connected
local sub2 = observable:Subscribe() --> Connected
local sub3 = observable:Subscribe() --> Connected

sub1:Destroy()
sub2:Destroy()
sub3:Destroy()

Note that emitted values may be observed like this

observable:Subscribe(function(value)
	print("Got ", value)
end)

--> Got a
--> Got b
--> Got c

Note that also, observables return a MaidTask which should be used to clean up the resulting subscription.

maid:GiveTask(observable:Subscribe(function(value)
	-- do work here!
end))

Observables over signals are nice because observables may be chained and manipulated via the Pipe operation.

tip

You should always clean up the subscription using a Maid, otherwise you may memory leak.

Functions

isObservable

Observable.isObservable(itemany) → boolean

Returns whether or not a value is an observable.

new

Observable.new(onSubscribe(subscriptionSubscription<T>) → MaidTask) → Observable<T>

Constructs a new Observable

local function observeAllChildren(parent)
	return Observable.new(function(sub)
		local maid = Maid.new()

		for _, item in pairs(parent:GetChildren()) do
			sub:Fire(item)
		end
		maid:GiveTask(parent.ChildAdded:Connect(function(child)
			sub:Fire(child)
		end))

		return maid
	end)
end

-- Prints out all current children, and whenever a new
-- child is added to workspace
local maid = Maid.new()
maid:GiveTask(observeAllChildren(workspace):Subscribe(print))

Pipe

Observable:Pipe(transformers{(observableObservable<T>) → Observable<T>}) → Observable<T>

Transforms the observable with the following transformers

Rx.of(1, 2, 3):Pipe({
	Rx.map(function(result)
		return result + 1
	end);
	Rx.map(function(value)
		return ("%0.2f"):format(value)
	end);
}):Subscribe(print)

--> 2.00
--> 3.00
--> 4.00

Subscribe

Observable:Subscribe(
fireCallbackfunction?,
failCallbackfunction?,
completeCallbackfunction?
) → MaidTask

Subscribes immediately, fireCallback may return a maid (or a task a maid can handle) to clean up

Show raw api
{
    "functions": [
        {
            "name": "isObservable",
            "desc": "Returns whether or not a value is an observable.",
            "params": [
                {
                    "name": "item",
                    "desc": "",
                    "lua_type": "any"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "boolean"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 74,
                "path": "src/rx/src/Shared/Observable.lua"
            }
        },
        {
            "name": "new",
            "desc": "Constructs a new Observable\n\n```lua\nlocal function observeAllChildren(parent)\n\treturn Observable.new(function(sub)\n\t\tlocal maid = Maid.new()\n\n\t\tfor _, item in pairs(parent:GetChildren()) do\n\t\t\tsub:Fire(item)\n\t\tend\n\t\tmaid:GiveTask(parent.ChildAdded:Connect(function(child)\n\t\t\tsub:Fire(child)\n\t\tend))\n\n\t\treturn maid\n\tend)\nend\n\n-- Prints out all current children, and whenever a new\n-- child is added to workspace\nlocal maid = Maid.new()\nmaid:GiveTask(observeAllChildren(workspace):Subscribe(print))\n```",
            "params": [
                {
                    "name": "onSubscribe",
                    "desc": "",
                    "lua_type": "(subscription: Subscription<T>) -> MaidTask"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<T>"
                }
            ],
            "function_type": "static",
            "source": {
                "line": 106,
                "path": "src/rx/src/Shared/Observable.lua"
            }
        },
        {
            "name": "Pipe",
            "desc": "Transforms the observable with the following transformers\n\n```lua\nRx.of(1, 2, 3):Pipe({\n\tRx.map(function(result)\n\t\treturn result + 1\n\tend);\n\tRx.map(function(value)\n\t\treturn (\"%0.2f\"):format(value)\n\tend);\n}):Subscribe(print)\n\n--> 2.00\n--> 3.00\n--> 4.00\n```",
            "params": [
                {
                    "name": "transformers",
                    "desc": "",
                    "lua_type": "{ (observable: Observable<T>) -> Observable<T> }"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "Observable<T>"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 135,
                "path": "src/rx/src/Shared/Observable.lua"
            }
        },
        {
            "name": "Subscribe",
            "desc": "Subscribes immediately, fireCallback may return a maid (or a task a maid can handle)\nto clean up",
            "params": [
                {
                    "name": "fireCallback",
                    "desc": "",
                    "lua_type": "function?"
                },
                {
                    "name": "failCallback",
                    "desc": "",
                    "lua_type": "function?"
                },
                {
                    "name": "completeCallback",
                    "desc": "",
                    "lua_type": "function?"
                }
            ],
            "returns": [
                {
                    "desc": "",
                    "lua_type": "MaidTask"
                }
            ],
            "function_type": "method",
            "source": {
                "line": 157,
                "path": "src/rx/src/Shared/Observable.lua"
            }
        }
    ],
    "properties": [],
    "types": [],
    "name": "Observable",
    "desc": "Observables are like an [signal](/api/Signal), except they do not execute code\nuntil the observable is subscribed to. This follows the standard\nRx API surface for an observable.\n\nObservables use a [Subscription](/api/Subscription) to emit values.\n\n```lua\n-- Constucts an observable which will emit a, b, c via a subscription\nlocal observable = Observable.new(function(sub)\n\tprint(\"Connected\")\n\tsub:Fire(\"a\")\n\tsub:Fire(\"b\")\n\tsub:Fire(\"c\")\n\tsub:Complete() -- ends stream\nend)\n\nlocal sub1 = observable:Subscribe() --> Connected\nlocal sub2 = observable:Subscribe() --> Connected\nlocal sub3 = observable:Subscribe() --> Connected\n\nsub1:Destroy()\nsub2:Destroy()\nsub3:Destroy()\n```\n\nNote that emitted values may be observed like this\n\n```lua\nobservable:Subscribe(function(value)\n\tprint(\"Got \", value)\nend)\n\n--> Got a\n--> Got b\n--> Got c\n```\n\nNote that also, observables return a [MaidTask](/api/MaidTask) which\nshould be used to clean up the resulting subscription.\n\n```lua\nmaid:GiveTask(observable:Subscribe(function(value)\n\t-- do work here!\nend))\n```\n\nObservables over signals are nice because observables may be chained and manipulated\nvia the Pipe operation.\n\n:::tip\nYou should always clean up the subscription using a [Maid](/api/Maid), otherwise\nyou may memory leak.\n:::",
    "source": {
        "line": 57,
        "path": "src/rx/src/Shared/Observable.lua"
    }
}