subscribable-things
A collection of reactive wrappers for various browser APIs.
This package provides factory functions which can be used to turn browser APIs into subscribable things. A subscribable thing can either be consumed directly with callback functions or by utilzing one of the popular libraries for reactive programming.
Usage
The subscribable-things
package is published on npm and can be installed as usual.
npm install subscribable-things
It exports individual functions for each wrapped browser API which are described in greater detail below. They can either be used directly by providing a callback function ...
import { mediaQueryMatch } from 'subscribable-things';
const subscribe = mediaQueryMatch('(max-width:600px)');
const unsubscribe = subscribe((isMatching) => console.log(isMatching));
unsubscribe();
... or by utilizing a library for reactive programming like RxJS ...
import { from } from 'rxjs';
import { mediaQueryMatch } from 'subscribable-things';
const mediaQueryMatch$ = from(mediaQueryMatch('(max-width:600px)'));
const subscription = mediaQueryMatch$.subscribe((isMatching) => console.log(isMatching));
subscription.unsubscribe();
... or Callbags ...
import fromObs from 'callbag-from-obs';
import observe from 'callbag-observe';
import { mediaQueryMatch } from 'subscribable-things';
const source = fromObs(mediaQueryMatch('(max-width:600px)'));
observe((isMatching) => console.log(isMatching))(source);
... or XStream ...
import { mediaQueryMatch } from 'subscribable-things';
import { fromObservable } from 'xstream';
const stream = fromObservable(mediaQueryMatch('(max-width:600px)'));
const unsubscribe = stream.subscribe((isMatching) => console.log(isMatching));
unsubscribe();
... or Bacon.js ...
import { fromESObservable } from 'baconjs';
import { mediaQueryMatch } from 'subscribable-things';
const eventStream = fromESObservable(mediaQueryMatch('(max-width:600px)'));
const unsubscribe = eventStream.onValue((isMatching) => console.log(isMatching));
unsubscribe();
... or Kefir.js.
import { fromESObservable } from 'kefir';
import { mediaQueryMatch } from 'subscribable-things';
const stream = fromESObservable(mediaQueryMatch('(max-width:600px)'));
const subscription = stream.observe({
value(isMatching) {
console.log(isMatching);
}
});
subscription.unsubscribe();
It is even possible to consume subscribable-things
as an async iterable by taking the little detour over RxJS and rxjs-for-await.
import { eachValueFrom } from 'rxjs-for-await';
import { from } from 'rxjs';
import { mediaQueryMatch } from 'subscribable-things';
const source$ = from(mediaQueryMatch('(max-width:600px)'));
for await (const isMatching of eachValueFrom(source$)) {
console.log(isMatching);
}
animationFrame(): SubscribableThing<number>
This function wraps the requestAnimationFrame()
method. It emits the current timestamp of each animation frame.
intersections(htmlElement: HTMLElement, options?: IntersectionObserverInit): SubscribableThing<IntersectionObserverEntry[]>
This function is a wrapper for the IntersectionObserver
.
mediaDevices(): SubscribableThing<MediaDeviceInfo[]>
This function is a wrapper for the enumerateDevices()
method of the Media Capture and Streams specification. It will also listen for the devicechange
event to emit a fresh list of devices whenever they change.
mediaQueryMatch(mediaQueryString: string): SubscribableThing<boolean>
This function is a wrapper for the matchMedia()
method. It will emit a new value whenever the result of matchMedia()
changes.
midiInputs(midiAccess: IMidiAccess): SubscribableThing<IMidiInput[]>
This function returns the currently available MIDI input devices. It accepts a MIDIAccess
object of the Web MIDI API.
midiOutputs(midiAccess: IMidiAccess): SubscribableThing<IMidiOutput[]>
This function returns the currently available MIDI output devices. It accepts a MIDIAccess
object of the Web MIDI API.
metrics(options: PerformanceObserverInit): SubscribableThing<PerformanceEntry[]>
This function is a wrapper for the PerformanceObserver
as defined by the Performance Timeline Level 2 specification.
mutations(htmlElement: HTMLElement, options: MutationObserverInit): SubscribableThing<MutationRecord[]>
This function is a wrapper for the MutationObserver
.
on(target: EventTarget, type: string, options?: boolean | AddEventListenerOptions): SubscribableThing<Event>
This function can be used to subscribe to events of a certain type dispatched from an EventTarget
.
online(): SubscribableThing<boolean>
This function wraps the onLine
property of the Navigator
and listens for the corresponding 'online'
and 'offline'
events on the Window
to emit updates.
permissionState(permissionDescriptor: PermissionDescriptor): SubscribableThing<PermissionState>
This function is a wrapper for the query()
method of the Permissions API. It will monitor the permission status to emit a new state whenever it gets updated.
reports(options?: IReportingObserverOptions): SubscribableThing<IReport[]>
This function is a wrapper for the ReportingObserver
of the Reporting API.
resizes(htmlElement: HTMLElement, options?: IResizesObserverOptions): SubscribableThing<IResizeObserverEntry[]>
This function is a wrapper for the ResizeObserver
of the Resize Observer specification.
unhandledRejection(coolingOffPeriod: number): SubscribableThing<any>
This function emits unhandled rejections. It will listen for the unhandledrejection
event to register possibly unhandled rejections. It will then wait for the cooling-off period to elapse before it emits the reason (aka the error) that caused the unhandled rejection. It is possible that a previously unhandled rejection gets handled later on in which case a rejectionhandled
event will be fired. If that happens during the cooling-off period nothing will be emitted by this function.
videoFrame(videoElement: HTMLVideoElement): SubscribableThing<{ now: number } & IVideoFrameMetadata>
This function wraps the requestVideoFrameCallback()
method of the given HTMLVideoElement
. It emits the current timestamp combined with the VideoFrameMetadata
object.
wakeLock(type: TWakeLockType): SubscribableThing<boolen>
This function simplifies the usage of the Screen Wake Lock API. It emits true when a wake lock could be acquired and emits false once the wake lock gets released by the browser. As long as the subscription is alive it will continuosly try to get a new wake lock if the current one gets released.