@pawsaw/subscription-manager
TypeScript icon, indicating that this package has built-in type declarations

1.0.1 • Public • Published

Subscription Manager

https://github.com/pawsaw/subscription-manager

What is it?

Subscription Manager - Lightweight JavaScript and TypeScript Utility for managing Subscriptions.

Why Subscription Manager?

  • Designed with one goal in mind: managing subscriptions.
  • No dependencies and an incredibly small footprint.
  • Developed in TypeScript, usable in TypeScript and JavaScript.
  • Elegant and easy to use.

The best way to describe a situation is often by Example.

Setup

npm i @pawsaw/subscription-manager

Subscription Manager API

Obtain an instance of Subscription Manager

At the beginning it is necessary to get an instance of the Subscription Manager.

import {
    createSubscriptionManager,
    SubscriptionManager,
    Subscription,
} from '@pawsaw/subscription-manager';

const sm: SubscriptionManager<string> = createSubscriptionManager();

Here string is the data type of the channel, as default. Other data types are acceptable, but less usual.

Here a Subscription Manager is created, where the channels are of the datatype number:

const sm: SubscriptionManager<number> = createSubscriptionManager<number>();

subscribe

We subscribe to a certain channel and define a callback function that takes any parameters. The parameters must be the same as in the counterpart, the publish method.

function onChatMessageReceived(msg: string): void {
    // ...
}

const sub = sm.subscribe('chatMessages', onChatMessageReceived);

The result of the subscribe method is a Subscription.

publish

To broadcast data, we use the publish method.

sm.publish('chatMessages', 'Hello World');

For all Subscribers on this channel the stored callback is called.

Typesafe publish and subscribe

In TypeScript it makes sense to get as much as possible out of static type checking.

interface OnChatMessageReceived {
    (msg: string): void;
}

const onChatMessageReceived: OnChatMessageReceived = (msg: string) => {
    // ...
};

const sub = sm.subscribe<OnChatMessageReceived>('chatMessages', onChatMessageReceived);

When publishing we can ensure the integrity of the parameters with respect to the type by explicitly specifying the type of the callback.

sm.publish<OnChatMessageReceived>('chatMessages', 'Hello World');

Note: The Subscription Manager may handle different types of callbacks on different channels.

free

If a subscription is no longer needed, be sure to free it.

sub.free();

Example (TypeScript): ChatService

We want to implement a ChatService that looks like this:

export interface OnChatMessageReceived {
    (msg: string): void;
}

export interface ChatService {
    onChatMessageReceived(listener: OnChatMessageReceived): Subscription;
}

... and a Client using it:

const chatService = ChatService.instance(); // ... access the instance somehow

const onChatMessageReceived: OnChatMessageReceived = (msg: string) => {
    console.log(`Got new message: ${msg}`);
};

// start listening for incomming messages
const sub = chatService.onChatMessageReceived(onChatMessageReceived);

// and if we're not longer interested in receiving messages ...
sub.free();

As you can see here, the ChatService may be a singleton (not mandatory), where several (!) clients may want to register to receive messages.

If a client is no longer interested in receiving the messages, he wants to free the Subscription.

Maybe you want to offer another method in the ChatService to get information about new ChatUsers, as the following example shows:

export interface OnChatMessageReceived {
    (msg: string): void;
}

export interface OnNewChatUser {
    (user: string): void;
}

export interface ChatService {
    onChatMessageReceived(listener: OnChatMessageReceived): Subscription;
    onNewChatUser(listener: OnNewChatUser): Subscription;
}

It is easy to see that the implementation of subscription management is quite complex and potentially repetitive.

Wouldn't it be nice to have a utility here that would make our work easier?

How to use the Subscription Manager?

import {
    createSubscriptionManager,
    SubscriptionManager,
    Subscription,
} from '@pawsaw/subscription-manager';

// [ ... ]

export interface OnChatMessageReceived {
    (msg: string): void;
}

export interface OnNewChatUser {
    (user: string): void;
}

export class ChatService {
    // Usually one SubscriptionManager per service
    private sm = createSubscriptionManager();

    private anyAsyncDatasource = any; // any async data source

    onChatMessageReceived(listener: OnChatMessageReceived): Subscription {
        return this.sm.subscribe('onChatMessageReceived', listener);
    }

    onNewChatUser(listener: OnNewChatUser): Subscription {
        return this.sm.subscribe('onNewChatUser', listener);
    }

    private initDataSource(): void {
        this.anyAsyncDatasource.receive((type: string, data: string) => {
            if (type === 'message') {
                this.sm.publish<OnChatMessageReceived>('onChatMessageReceived', data);
            } else if (type === 'user') {
                this.sm.publish<OnNewChatUser>('onNewChatUser', data);
            }
        });
    }
}

That's it folks!

Stay tuned and keep on coding.

Readme

Keywords

none

Package Sidebar

Install

npm i @pawsaw/subscription-manager

Weekly Downloads

0

Version

1.0.1

License

MIT

Unpacked Size

15.7 kB

Total Files

11

Last publish

Collaborators

  • pawel.sawicki