Flow empowers AsyncGenerators to provide a great streaming experience.
The goal is to identify what matters most to design a robust stream implementation while keeping the API as simple as possible.
To understand this necessity, please refer to the MANIFEST.
Flow is great for automation:
async function automation(signal: AbortSignal) {
// Let's assume we have:
const temperatureObserver: ReadableFlow<number> = /*...*/; // emits the temperature of a device
const airCoolingOnOffWriter: Drain<boolean> = /*...*/; // turns on/off an air cooling device
// Then we can link them like this:
// 3) the airCoolingOnOffWriter consumes the created flow and turns on/off the air cooling device acoording to the received temperature values
await airCoolingOnOffWriter.drain(
temperatureObserver
// 1) for each temperature values sent by the temperatureObserver, we return true isf it exceeds 28 degrees
.map((temperature: number) => temperature > 28.0)
// 2) we emit only disctinct values, to prevent the air cooling device to be spammed with identical commands
.distinct(),
signal,
);
}
interface Drag {
readonly originX: number;
readonly originY: number;
readonly currentX: number;
readonly currentY: number;
readonly deltaX: number;
readonly deltaY: number;
}
async function main(signal: AbortSignal) {
const readable = ReadableFlow.when<PointerEvent>(window, 'pointerdown')
.flatMap((event: PointerEvent): ReadableFlow<Drag> => {
const originX: number = event.clientX;
const originY: number = event.clientY;
return (
ReadableFlow.when<PointerEvent>(window, 'pointermove')
.takeUntil(ReadableFlow.when(window, 'pointerup'))
.map((event: PointerEvent): Drag => {
const currentX: number = event.clientX;
const currentY: number = event.clientY;
return {
originX,
originY,
currentX,
currentY,
deltaX: currentX - originX,
deltaY: currentY - originY,
};
})
);
});
for await (const value of readable.open(signal)) {
console.log('drag', value);
}
}
yarn add @xstd/flow
# or
npm install @xstd/flow --save