signals.ts

1.0.4 • Public • Published

Signals.ts

Tests

Signals implementation for TypeScript.

It's a simple pub-sub message bus architecture that's completely decoupled from any UI or other component.

Inspired by JS-Signals which was inspired by AS3-Signals.

Why another implementation

I used many implementations through the years, manly Miller Medeiros' one.

What I though was missing was:

  • TypeScript support
  • Two way decoupled communication

Installation

$ npm i --save signals.ts

or

$ yarn add signal.ts

or

$ echo 'whatever package manager you use... the package is on npm.com 🙂'

Basic usage

//signals.ts --------------------------

import {Signal} from 'signals.ts';
export const MY_SIGNAL = new Signal();
export const MY_OTHER_SIGNAL = new Signal();
//...
// dispatcher.ts ----------------------
import {MY_SIGNAL} from './signals';

MY_SIGNAL.dispatch();
// listener.ts ------------------------

MY_SIGNAL.add(() => {
  //do something about it
})

// or

MY_SIGNAL.addOnce(() => {
  //do something about it just the first time the signal is received
})

Sending data

const SHOW_NOTIFICATION = new Signal<{title : string, body : string}>();

SHOW_NOTIFICATION.dispatch({title : 'Error', `There's a snake in your boot`});

Receiving data (asynchronously)

const SHOW_DIALOG = new Signal<{title : string, body : string, buttons : Array<'ok' | 'cancel' | 'yes' | 'no'>}>();
// the enquirer
const [response] = //response are always an array
  await SHOW_DIALOG.dispatch({title : 'Danger', body : 'This button will destroy the world. Do you want to proceed?', buttons : ['yes', 'no']})
// the dialog view component
SHOW_DIALOG.add((config) => {
  return new Promise(resolve => {
  this.show(config)
    .onResponse(resolve)
  });
})

Controlling propagation

//any failed response, according to the listenerSuccessTest will stop propagation
const APP_WILL_CLOSE = new Signal({propagate : 'any-fail', listenerSuccessTest: val => val === true})
// The app controller
const responses = await APP_WILL_CLOSE.dispatch()

const shouldProceed = !response.some(dirty => dirty = false)


// any listening editors

APP_WILL_CLOSE.add(() => {
  if(this.inABadMood) {
    return false;
  }
});

Retaining early signal dispatchment

export const APP_WAS_INITIALIZED = new Signal({memoize : true});
// app bootstrapping controller

await this.bootstrap()
APP_WAS_INITIALIZED.dispatch();
// some component we're not sure will be listening in time

// listener will be called even if addOnce is called after the 
// signal was already dispatched
APP_WAS_INITIALIZED.addOnce(() => {
  this.doSomething()
})

Detaching/Suspending a listener

Adding a listener returns a binding object that can be used to temporarily suspend or permanently detach the listener

const fn1Binding = SOME_SIGNAL.add(functionOne);
SOME_SIGNAL.add(functionTwo);
SOME_SIGNAL.dispatch() //will reach functionOne and functionTwo
fn1Binding.suspend()
SOME_SIGNAL.dispatch() //will reach functionTwo only
fn1Binding.resume()
SOME_SIGNAL.dispatch() //will reach functionOne and functionTwo

fn1Binding.detatch()
SOME_SIGNAL.dispatch() //will reach functionTwo only

fn1Binding.suspend() //will throw Error
fn1Binding.resume() //will throw Error

License

Running Tests

$ yarn
$ yarn test

Readme

Keywords

none

Package Sidebar

Install

npm i signals.ts

Weekly Downloads

2

Version

1.0.4

License

Apache-2.0

Unpacked Size

24.5 kB

Total Files

10

Last publish

Collaborators

  • aekidna