In the previous entry, we covered a bit more about Observable creation, but once again we were in the weeds showing how the magic is made. Now that you understand the basics, let's make it easy for you going forward. Built into RxJS are a number of predefined ways of creating Observables such as:
Conversions:
bindCallback
- binds a callback to an ObservablebindNodeCallback
- binds a Node.js style error callback to an Observablefrom
- converts a number of structures to an Observable such as Arrays, Promises, Observables, Iterables, etc.fromEvent
/fromEventPattern
- converts DOM events andEventEmitter
Creation:
generate
- creates an Observable based upon a for loop behaviorempty
- creates an Observable that emits only acomplete
interval
- creates an Observable that emits on the given time sequencenever
- creates an Observable that never emits a valueof
- creates an Observable from a list of argumentsrange
- creates an Observable from a range of numbersthrowError
- creates an error Observable which throws the given errortimer
- creates an Observable that emits at the first time, and repeats on the period time if given
Today, we're going to talk a little bit about the creation operations since they are the easiest way to get started.
The most common used way of creating Observables is via the of
factory. This takes a number of arguments, followed by an optional Scheduler of your choosing which determines how the values are emitted.
import {
asapScheduler,
of
} from 'rxjs';
// Using the default scheduler
const source1$ = of(1, 2, 3);
// Using the ASAP scheduler
const source2$ = of(4, 5, 6, asapScheduler);
We can then listen for the results with a nice tracer for which sequence is which:
const observer = (id: number) => {
return {
next: (x: number) => console.log(`ID ${id} Next: ${x}`),
complete: () => console.log(`ID ${id} Complete!`)
};
}
const subscription1 = source1$.subscribe(observer(1));
const subscription2 = source2$.subscribe(observer(2));
Running that via ts-node
gives us the following:
$ npx ts-node 03/index.ts
ID 1 Next: 1
ID 1 Next: 2
ID 1 Next: 3
ID 1 Complete!
ID 2 Next: 4
ID 2 Next: 5
ID 2 Next: 6
ID 2 Complete!
Another way of creating Observables is via the range
operator which creates a sequence of numbers with a start value, a number of elements to produce, and an optional scheduler once again to control the concurrency. You'll notice a common theme here that all creation operations take in an optional scheduler. This is for testing purposes but also allows you to control the concurrency and where it runs.
import {
asapScheduler,
range
} from 'rxjs';
// Without a scheduler
const number1$ = range(0, 3);
// With the asap scheduler
const number2$ = range(3, 3, asapScheduler);
Using the above subscription techniques to track which one we're listening to, let's run through the values.
$ npx ts-node 03/index.ts
ID 1 Next: 0
ID 1 Next: 1
ID 1 Next: 2
ID 1 Complete!
ID 2 Next: 3
ID 2 Next: 4
ID 2 Next: 5
ID 2 Complete!
Finally, let's cover one last creation operation, the generate
function. This acts as your standard for loop like this:
for (let i = 0; /* initial value */
i < 10; /* condition */
i++ /* increment */) {
// Do something with the i value
}
In the same way, our generate
function acts the same way with the following arguments:
generate<Source, Result>(
initialValue: Source,
condition: (value: Source) => bool
iterate: (value: Source) => Source,
resultSelector: (value: Source) => Result
);
Using this knowledge, we can easily emit three values such as:
import {
generate
} from 'rxjs';
const number$ = generate(
43,
i => i < 46,
i => i + 1,
i => String.fromCharCode(i)
);
const subscription = number$.subscribe({
next: x => console.log(`Next: ${x}`),
complete: () => console.log(`Complete!`)
});
Running our solution now will look like this where we transformed our numbers into characters based upon their character code:
$ npx ts-node 03/index.ts
Next: +
Next: ,
Next: -
Complete!
Stay tuned to tomorrow's session where we'll cover more about creation, such as values over time and conversions!