EventEmitter
comparison
Let us consider this example, use of EventEmitter
:
Copy import { EventEmitter } from "events";
const eventEmitter = new EventEmitter();
eventEmitter.on("text", text => console.log(text));
eventEmitter.once("time", time => console.log(time));
eventEmitter.emit("text", "hi!"); //Prints "hi!"
eventEmitter.emit("time", 123); //Prints "123"
eventEmitter.emit("time", 1234); //Prints nothing ( once )
In EVT the recommended approach is to give every event it's Evt
instance. Translation of the example:
Copy import { Evt } from "evt";
//Or import { Evt } from "https://evt.land/x/evt/mod.ts" on deno
const evtText = Evt.create<string>();
const evtTime = Evt.create<number>();
evtText.attach(text => console.log(text));
evtTime.attachOnce(time => console.log(time));
evtText.post("hi!");
evtTime.post(123);
evtTime.post(1234);
However, the traditional approach that consists of gathering all the events in a single bus is also an option.
Copy import { Evt, to } from "evt";
const evt = Evt.create<
[ "text", string ] |
[ "time", number ]
>();
evt.$attach(to("text"), text => console.log(text));
evt.$attachOnce(to("time"), time => console.log(time));
evt.post(["text", "hi!"]);
evt.post(["time", 123]);
evt.post(["time", 1234]);
RxJS comparison
"Get started" examples.
Copy import { fromEvent } from "rxjs";
import { throttleTime, map, scan } from "rxjs/operators";
fromEvent(document, "click")
.pipe(
throttleTime(1000),
map(event => event.clientX), // (TS: clientX does not exsist on type Event)
scan((count, clientX) => count + clientX, 0)
)
.subscribe(count => console.log(count))
;
/* ------------------------------ */
import { Evt, throttleTime } from "evt";
Evt.from(document, "click")
.pipe(
throttleTime(1000),
event => [ event.clientX ],
[(clientX, count) => [ count + clientX ], 0]
)
.attach(count => console.log(count))
;
RxJS operators vs EVT operator
Consider that we have an emitter for this data type:
Copy type Data = {
type: "TEXT";
text: string;
} | {
type: "AGE";
age: number;
};
We want to get a Promise<string>
that resolves with the next text event.
Copy import { Subject } from "rxjs";
import { filter, first, map } from "rxjs/operators";
const subject = new Subject<Data>();
const prText = subject
.pipe(
filter(
(data): data is Extract<Data, { type: "TEXT" }> =>
data.type === "TEXT"
),
first(),
map(data => data.text)
)
.toPromise()
;
/* ---------------------------------------------------------------- */
import { Evt } from "evt";
const evt = new Evt<Data>();
const prText = evt.waitFor(
data => data.type !== "TEXT" ?
null : [data.text]
);
Let us consider another example involving state encapsulation. Here we want to accumulate all texts events until "STOP"
Copy import { Subject } from "rxjs";
import { map, filter, takeWhile, scan } from "rxjs/operators";
const subject = new Subject<Data>();
subject
.pipe(
filter(
(data): data is Extract<Data, { type: "TEXT" }> =>
data.type === "TEXT"
),
map(data=> data.text),
takeWhile(text => text !== "STOP"),
scan((prev, text) => `${prev} ${text}`, "=>")
)
.subscribe(str => console.log(str))
;
/* ---------------------------------------------------------------- */
import { Evt } from "evt";
const evtData = new Evt<Data>();
evtData.$attach(
[
(data, prev) =>
data.type !== "TEXT" ?
null :
data.text === "STOP" ?
"DETACH" :
[`${prev} ${data.text}`]
,
"=>"
], //<= Stateful fλ operator
str => console.log(str)
);
Where to start
The API reference documentation is full of runnable examples that should get you started in no time.