πΎUnits
Units are the most important part of ActiveJS, they are responsible for holding the state of your single page application. Units can also be used independently, without any further knowledge of ActiveJS.
Units are specialized, reactive data structures based on JavaScript's native data structures like boolean, string or array.
For example, ListUnit is an elaborate array like data structure which is also an Observable and implements all the Array.prototype methods in a way that, any mutation caused by these methods, emits a new array with the mutations applied to it.
The actual value is stored inside the Unit and can be accessed via the value() method.
All the available Units are BoolUnit, NumUnit, StringUnit, ListUnit, DictUnit, and GenericUnit.
βΆ Initializing a Unit
A Unit has several configuration options, including an optional initial-value.
Every type of Unit has a designated default value. NumUnit has 0 as the default value, and StringUnit has ''. That's why in the above example the unit1 and unit2 are equivalent.
π Accessing the value
As you might've noticed, when subscribing to the unit1, a value immediately gets logged to the console even though we haven't dispatched any value yet. If you are only interested in future values you can use future$ Observable, which doesn't replay the last value on subscription, it only emits future values.
π‘ Dispatching a value
All Units ignore any invalid value dispatch, Units only accept their designated value type, except the GenericUnit, because it's designed to accept and store all types of values.
There are two ways to dispatch a new value. You can pass a value or a value-producer-function to generate a new value to the dispatch method, the dispatch method returns true or false depending on the success of dispatch, which you can use to make any further decisions.
π Using the Cached values
All Units cache 2 values by default, it allows us to go back and forth through these cached-values in such a way that it doesn't affect the cached-values, only the current-value changes. The caching mechanism works almost exactly like browser history.
The cache can be utilized in many ways, but probably the most common use case would be undo and redo capabilities. For undo feature we can use goBack method and for redo we can use goForward method respectively.
To dive into more details, see Caching to understand how it works.
βΊ Clear & Reset
Resetting a Unit to it's initial-value is as easy as calling a method. Similarly clearing the value is also that easy.
π Immutability
To demonstrate immutability we'd need a different kind of Unit because the NumUnit deals with a primitive type number which is already immutable.
Let's take a ListUnit to create a reactive, array like data structure.
We just created an immutable Unit, that's all it takes, a configuration flag.
β Mutation check
See Immutability guide for more details.
β Persistence
To make a Unit persistent, all we need is a unique id so that the Unit can identify itself in the localStorage, and a configuration flag.
That's it, this StringUnit is persistent, it already saved its default value to localStorage.
β Persistence check
See Persistence guide for more details.
π Replay and Replay-ness
Every Unit immediately provides the value when subscribed, by default, but maybe you only want the future values. For that purpose, every Unit has a built-in alternative Observable that doesn't emit immediately on subscription.
You can also turn the default replay-ness off.
π Manual Replay
Imagine a Unit is being used as a source for an API request, and you have a "refresh" button to trigger the request again. For this and many other scenarios, Units provide a manual replay method.
β Freezing
If you want a Unit to stop accepting new values, in scenarios where the state is not supposed to change. All you need to do is this:
See Freezing guide for more details.
π Muting
If you want a Unit to stop emitting new values, but keep accepting new values, in scenarios where you aren't interested in new values but still don't want to lose them. All you need to do is mute the Unit.
See Muting guide for more details.
π
Events
Every Unit emits an event for every operation performed on it, you can tap into these events to take some other action.
There's an event for almost every operation that can be performed on a Unit, for example:
See Events guide for more details.
π Units vs native data structures
Units can not be used as drop-in replacements for native data structures.
However, in most scenarios, a Unit instance can be used directly instead of Unit.value()
Every Unit implements valueOf and toString methods. JavaScript automatically invokes these methods when encountering an object where a primitive or string value is expected, respectively. Hence NumUnit, StringUnit, and BoolUnit can be used similar to their primitive counterparts.
Additionally, Units also implement their counterparts prototype methods like NumUnit implements Number.prototype methods to make it easier to work with the stored value. Similarly, ListUnit implements all the Array.prototype methods, StringUnit implements all the String.prototype methods, and so on.
number vs NumUnit
number vs NumUnitarray vs ListUnit
There are even more cases where you can treat a Unit just like a native data structure, barring a few exceptions like ListUnit and DictUnit don't have key-based property access and assignment, they use get and set methods instead. And the fact that BoolUnit, NumUnit or StringUnit aren't actually primitives, the typeof operator will only return object.
More Examples
π Units vs BehaviorSubject
Unit
BehaviorSubject
Replays value on subscription
β
β
Can be configured to not replay value on subscription
β
β
Allows to listen to only future values
β
β
Accepts an initial-value
β
β
Can cache more than one value
β
β
Allows cache-navigation
β
β
Validates dispatched values
β
β
Specialized for specific data structures
β
β
Can re-emit/replay last value manually
β
β
Can be frozen
β
β
Can be muted
β
β
Can be immutable
β
β
Can be persistent
β
β
Can be reset
β
β
Configuration Options
The configuration options can be passed at the time of instantiation. All the configuration options are optional. You can set them per Unit or you can also set most of them globally. See Configuration for more details.
Last updated
Was this helpful?