Abstract Class: Disposable
Base class for everything that has a lifetime: it owns timers, listeners and child objects and releases them all in one dispose(). Extend it for a helper your plugin creates (a poller, an API client with a connection); Plugin, Sensor, Actuator and Action already extend it.
Resources registered through own(), every(), after() or listen() are released in reverse registration order when dispose() is called, so a subclass never has to remember to clean up after itself. The registration helpers are protected on purpose: only the owner decides what lives and dies with it.
Registering anything after dispose() throws, so a late callback cannot leak a timer into a dead object.
Plugins, sensors and actuators are Disposables; the runtime calls their dispose() when a signal is removed or edited and when the instance stops, so plugin code rarely calls it itself. A class you own() should extend Disposable too (or implement DisposableLike) and register its own timers and listeners the same way:
class Poller extends Disposable {
start() { this.every(5000, () => void this.poll()) }
}
// in the plugin: readonly poller = this.own(new Poller()) (call poller.start() from start())
A callback given to every(), after() or listen() that throws is an uncaught exception, which
ends the worker (the host restarts it); catch errors inside it, and report them with the
plugin's log or status. A callback that returns a rejected promise goes to
Plugin.unhandledRejection().
Extended by
Implements
Constructors
Constructor
new Disposable():
Disposable
Returns
Disposable
Properties
MAX_TIMER_MS
readonlystaticMAX_TIMER_MS:2147483647=2_147_483_647
the largest delay setTimeout/setInterval honour; Node turns anything longer into 1 ms
Accessors
isDisposed
Get Signature
get isDisposed():
boolean
true from the moment dispose() starts, not when it finishes
Returns
boolean
Methods
dispose()
dispose():
Promise<void>
Releases everything registered with this object. Plugin code seldom needs it: the runtime disposes plugins, sensors and actuators, and own() disposes children. Call it yourself for an object you created without own(), or to end a child early.
Runs all teardowns in reverse registration order and keeps going when one fails. Idempotent: every call returns the same promise, so a second caller also waits for async teardowns.
Returns
Promise<void>
Throws
AggregateError collecting every teardown error, after all teardowns have run
Implementation of
onDispose()
protectedonDispose(teardown):void
Registers a callback that runs on dispose(), for cleanup the helpers don't cover (closing a socket, flushing a buffer). Async callbacks are awaited one after the other, last registered first, so a flush can use what was registered before it. Keep the total under the five seconds a stop has.
Parameters
teardown
Returns
void
Throws
Error if already disposed
useClock()
protecteduseClock(clock):void
Sets the clock for every() and after() calls from now on, unless one is set already; without one they run on the system clock. Timers started before keep the clock they started on. Plugin, Sensor and Actuator set it from the plugin's context.
Parameters
clock
Clock | undefined
Returns
void
currentClock()
protectedcurrentClock():Clock
The clock this object runs on: every() and after() use it, and a Disposable that isn't a
plugin, sensor or actuator reads the time from it (this.currentClock().now()).
Returns
own()
protectedown<T>(resource):T
ties the lifetime of a child resource to this object; returns it so construction and registration fit in one expression. A Disposable child without a clock of its own runs on this one's, looked up when a timer starts, so a chain of owners (plugin → client → poller) shares the plugin's clock. Timers a child starts in its constructor, before it is owned, run on the system clock.
Type Parameters
T
T extends DisposableLike
Parameters
resource
T
Returns
T
every()
protectedevery(ms,fn): () =>void
runs fn every ms milliseconds until disposed or until the returned cancel function is called. The first run is after ms, not at once; call fn yourself first if you want an immediate run. Runs are not queued: a slow async fn can overlap its next run, so guard it yourself if needed.
Parameters
ms
number
fn
() => void
Returns
() => void
Throws
RangeError unless 0 < ms <= MAX_TIMER_MS
after()
protectedafter(ms,fn): () =>void
runs fn once after ms milliseconds unless disposed before; returns a cancel function. Both firing and cancelling forget the teardown, so repeated use does not accumulate entries. Delays beyond MAX_TIMER_MS are scheduled in steps, so they don't fire early.
The delay counts elapsed time, not wall-clock time: a clock step (an NTP sync after boot) is not noticed. For a deadline given as a wall-clock time, wait in shorter slices and re-check the time each time.
Parameters
ms
number
fn
() => void
Returns
() => void
Throws
RangeError for negative or non-finite delays
listen()
protectedlisten(emitter,event,listener):void
Subscribes listener to event of an EventEmitter (or anything with on/off) and removes it
again on dispose(), so a long-lived emitter such as the plugin's poller does not keep a
disposed sensor alive. Prefer it to calling emitter.on yourself.
Parameters
emitter
event
string | symbol
listener
Returns
void