Skip to content

An event bus system that allows listener to be retroactive

Notifications You must be signed in to change notification settings

jcalixte/retrobus

Repository files navigation

logo

npm npm

Retro Bus

Retrobus is a simple event bus for your JavaScript/TypeScript application.

Features

  • Trigger callback even if the listener is added after the event was first emitted with the property retro,
  • JavaScript / TypeScript,
  • Framework agnostic,
  • 0 dependencies.

Installation

npm:

npm install retrobus

yarn:

yarn add retrobus

pnpm:

pnpm add retrobus

Usage

Retrobus implements 4 methods:

Emit an event

import { emit } from 'retrobus'

emit('authenticated', {
  isUserAuthenticated: true
})

emit takes any additionnal parameters after the name. Theses parameters will be passed to the listener callbacks.

Listen to an event

import { addEventBusListener } from 'retrobus'

const fetchUserProfile = ({ isUserAuthenticated }) => {
  if (isUserAuthenticated) {
    console.log('user is authenticated!')
  }
}

addEventBusListener('authenticated', fetchUserProfile, {
  once: true,
  retro: true
})

addEventBusListener has multiple options that allow you to configure the listener's behavior:

name type default description
retro boolean false call retroactively the callback if the event was emitted before the listener
retroStrategy 'last-one' | 'all' 'last-one' Define the strategy when calling previous emitted events. If retroStrategy is set to all, every emitted events will be called, from oldest to newest. If retroStrategy is set to last-one, only the last emitted event will be retractively called. Default to last-one. Ignored if retro is false.
once boolean false remove the callback right after beeing called. If retro is true and if the event was previously emitted, the callback is directly called then removed.
unique boolean false make sure the callback is only added once

addEventBusListener returns a callback to directly unsubscribe the listener added.

Remove a listener

import { addEventBusListener, removeEventBusListener } from 'retrobus'

const fetchUserProfile = ({ isUserAuthenticated }) => {
  if (isUserAuthenticated) {
    console.log('user is authenticated!')
  }
}

addEventBusListener('authenticated', fetchUserProfile, {
  once: true,
  retro: true,
  unique: true
})

removeEventBusListener('authenticated', fetchUserProfile)

Clear listeners

import { addEventBusListener, clearEventBusListeners } from 'retrobus'

const fetchUserProfile = ({ isUserAuthenticated }) => {
  if (isUserAuthenticated) {
    console.log('user is authenticated!')
  }
}

addEventBusListener('authenticated', fetchUserProfile, {
  once: true,
  retro: true
})

clearEventBusListeners('authenticated')
clearEventBusListeners() // clear all event listeners

Clear emitted events

With clearEmittedEvents(name), you can clear all the events from a specific key already emitted. If there is no parameter when calling the function, then all the emitted events are cleared.

Create an event bus

import { createEventBus } from 'retrobus'

const eventBus = createEventBus<{ a: string; b: string }>('authentication')

eventBus.addEventBusListener((payload) => {
  console.log(payload.a, payload.b)
})

eventBus.emit({ a: 'Hello', b: 'World' })

event name can be defined with strings or Symbols

These 2 implementations work:

import { createEventBus } from 'retrobus'

const eventBus = createEventBus<{ a: string; b: string }>() // default to Symbol()

eventBus.addEventBusListener((payload) => {
  console.log(payload.a, payload.b)
})

eventBus.emit({ a: 'Hello', b: 'World' })
import { createEventBus } from 'retrobus'

const eventName = Symbol('authentication')

const eventBus = createEventBus<{ a: string; b: string }>(eventName)

eventBus.addEventBusListener((payload) => {
  console.log(payload.a, payload.b)
})

eventBus.emit({ a: 'Hello', b: 'World' })

Add event listener examples with framework

VueJS

<template>
  <button @click="log">Greetings!</button>
</template>

<script>
import { addEventBusListener, emit, removeEventBusListener } from 'retrobus'

export default {
  name: 'HelloWorld',
  mounted() {
    addEventBusListener('log', this.greetings)
  },
  beforeDestroy() {
    removeEventBusListener('log', this.greetings)
  },
  methods: {
    greetings() {
      console.log('Hello world!')
    },
    log() {
      emit('log')
    }
  }
}
</script>

React

import { addEventBusListener, emit } from 'retrobus'

const HelloWorld = () => {
  useEffect(() => {
    const greetings = () => console.log('Hello World')

    return addEventBusListener('log', greetings)
  }, [])

  return <button onClick={() => emit('log')}>Greetings!</button>
}

Angular

// content.component.ts
import { Component, OnDestroy } from '@angular/core'
import { addEventBusListener, emit, removeEventBusListener } from 'retrobus'

@Component({
  selector: 'app-content',
  templateUrl: 'content.component.html',
  styleUrls: ['content.component.scss']
})
export class ContentComponent implements OnDestroy {
  constructor() {
    addEventBusListener('log', this.greetings)
  }

  ngOnDestroy() {
    removeEventBusListener('log', this.greetings)
  }

  greetings() {
    console.log('Hello World')
  }

  log() {
    emit('log')
  }
}
<!-- content.component.html -->
<button (click)="log()">Greetings!</button>

Credits

Logo created with Tabler Icons.

About

An event bus system that allows listener to be retroactive

Resources

Stars

Watchers

Forks

Packages

No packages published