npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

reactive-observables

v2.0.0-beta-2

Published

Framework-agnostic observables and computed properties similar to Knockout and Vue, built on RxJS

Downloads

985

Readme

alt text

Build Status Wallaby.js codecov Codacy Badge

Reactive Observables

Framework-agnostic observables and computed properties that update when their dependencies change, a la Knockout or Vue.js observables, built on and compatible with RxJS.


Different words for the same thing:

RxJS and some frameworks like Knockout and Vue use different implementations of the observable pattern and different definitions for an observable.

An observable in RxJS is an abstract stream that simply provides a new value to subscribers when .next() is called on it. They are not stateful, and the last used value is not stored. Subscribers always get notified, regardless of whether the new value is different from the last one.

An observable in Knockout is meant to be used like a variable. It stores a value that can be set and accessed. Reads and writes to it are tracked, so that Computed values which are dependent on the observable will update when it updates. Subscribers are only notified when the new value is different.

An observable in Knockout is basically the same as a BehaviorSubject in RxJS. There is no equivalent to a knockout computed value in RxJS.

This library attempts to replicate that additional dependency tracking and change-checking that you get with those other frameworks, but in the vernacular and API of RxJS. At the same time it aims to create a agnostic observable library that can be used independent of—or in the absence of—a front-end framework.


Observables

TrackedSubject is equivalent to ko.observable and similar to Vue.observable.

import { TrackedSubject } from "computed-observable";

const foo = new TrackedSubject(3);

// Get the value
foo.value; // 3

// Set the value
foo.value = 5;

// Subscribe to changes
foo.subscribe(newValue => {
    console.log(`Foo is now ${ newValue }`);
});

As a Decorator

Can also be used as a TypeScript decorator

class Bar {
    @tracked
    foo = 3;

    constructor() {
        // Use just like any property
        foo = 5;

        // Subscribe to changes on the property
        subscribe(this, "foo", newValue => {
            console.log(newValue);
        });
    }
}

Computed Observables

TrackedComputedSubject is the equivilant of ko.computed. Automatically updates when dependencies update.

import { TrackedComputedSubject } from "computed-observable";

const foo = new TrackedSubject(3);

// Create the computed with a getter function
const doubled = new TrackedComputedSubject(() => foo.value * 2);

// Foo gets changed
foo.value = 5;

// Computed automatically updates
doubled.value; // 10;

// Subscribe to the computed as you would any observable
doubled.subscribe(newValue => {
    console.log(`New value is ${ newValue }`);
});

As a Decorator

Can also be used as a TypeScript decorator:

class Bar {
    @tracked
    foo = 3;

    @computed
    get doubled() {
        return foo * 2;
    }

    constructor() {

        // Foo gets changed
        foo = 5;

        // Computed automatically updates
        doubled; // 10

        // Subcribe to the property
        subscribe(this, "doubled", newValue => {
            console.log(newValue);
        });
    }
}

Arrays

The equivalent of ko.observableArray. Arrays are treated as immutable and are frozen. Shallow equal comparer is used to determine whether array has changed.

import { TrackedArray } from "computed-observable";

const array = new TrackedArray([1, 2, 3]);

// Get the value
array.value;

// Set the value
array.value = [4, 5, 6];

// Push a new value
array.value = [...array.value, 7];

// Not allowed, will throw error
array.value.push(8);

// Built-in array functions still available
const doubled = array.value.map(n => n * 2);

// Subscribe to changes
array.subscribe(newValue => console.log(`New value is ${ newValue }`));

As a Decorator

Can also be used as a TypeScript decorator:

class Bar {
    @tracked
    foo = [1, 2, 3];

    constructor() {
        // Get the array
        foo; // [1, 2, 3]

        // Set the array
        foo = [4, 5, 6];

        // Push to the array
        foo = [...foo, 7];

        // Subscribe to the array
        subscribe(this, "foo", newValue => {
            console.log(newValue);
        });
    }
}