0.0.8 • Published 10 months ago

its-signals v0.0.8

Weekly downloads
-
License
GPL-3.0-only
Repository
github
Last release
10 months ago

npmjs publish npm version

It's signals, Jerry. It's signals

-- I can't believe: WE ALREADY DISCUSSED THIS!
-- Yeah, but how could you be so sure?
-- 'Cause it's signals, Jerry. It's signals! Don't you know it.. all right.
Did she even ask you, what you were doin' tomorrow night, if you were busy?
-- No.
-- She calls you today and she doesn't make a plan for tomorrow? What is that? It's Saturday night!
-- Yeah.
-- What is that? It's ridiculous! You don't even know, what hotel she's staying at, you can't call her.
That's a signal, Jerry, That's a SIGNAL!

-- Maybe you're right.
-- Maybe I'm right? Of course I'm right.

It's signals Jerry, signals!

Motivation

In JavaScript, while event handling is ubiquitous, many libraries deviate from the well-established patterns found in other languages, such as the observer pattern or the signal-slot mechanism popularized by frameworks like Qt in C++. This divergence can make these libraries feel awkward and unintuitive to use. The lack of standardized patterns for asynchronous programming often leads to fragmented approaches and increased complexity in managing events.

This signals module aims to bridge this gap by introducing a straightforward and safe event handling mechanism that aligns with these time-tested patterns. By adopting a familiar interface for connecting, emitting, and disconnecting signals and slots, it simplifies the process of building responsive and maintainable applications in JavaScript.

Usage guide

The Signal class provides a way to manage asynchronous event-driven communication in your application. You can create signals that emit values, and connect slots (functions or other signals) that respond to those emissions.

Creating a Signal

To create a new signal instance, simply instantiate the Signal class:

const signal = new Signal()

You can create a signal from a DOM element that triggers events using the static Signal.fromEvent method:

const button = document.getElementById("myButton")
const clickSignal = Signal.fromEvent(button, "click")

This creates a signal that listens to the "click" event on the specified element. When the event occurs, the signal emits the value of the event's target (i.e., e.target.value).

Note: The element must be an instance of EventTarget.

Connecting Signals with Slots

Slots may be any handler functions or other Signal instances that you can connect to a signal. When the signal is emitted, all connected slots are scheduled to be invoked asynchronously with the emitted arguments.

To connect a function as a slot:

function slot(value) {
    console.log("Received:", value)
}

signal.connect(slot)

You can connect another Signal instance as a slot. This effectively chains the signals so that emitting the first signal will cause the connected signal to emit as well.

const signalA = new Signal()
const signalB = new Signal()

signalA.connect(signalB)

Trigger Mechanics

To trigger (emit) a signal and invoke its all connected slots, simply call:

signal.emit(value)

The emit method schedules each connected slot to be called asynchronously using queueMicrotask, ensuring that the slots are invoked after the current execution context completes.

Passing Arguments

All arguments passed to emit are forwarded to the connected slots:

signal.emit(arg1, arg2, arg3)

Each slot will receive these arguments:

function slot(a, b, c) {
    console.log(a, b, c)
}

Disconnecting Slots

To disconnect a specific slot:

signal.disconnect(slot)

After disconnection, the slot will no longer be invoked when the signal is emitted.

To disconnect all slots:

signal.disconnect()

This clears all connected slots from the signal.

Checking Connection Status

You can check if the signal has any connected slots using the isConnected method:

if (signal.isConnected()) {
    // Signal has at least one connected slot
}

This method returns a boolean indicating whether there are any slots connected.

Examples

const signal = new Signal()

function slot(value) {
    console.log("Slot received:", value)
}

signal.connect(slot)
signal.emit("Hello, world!")
// Output: Slot received: Hello, world!

Connecting Multiple Slots

const signal = new Signal()

function slot1(value) {
    console.log("Slot 1 received:", value)
}

function slot2(value) {
    console.log("Slot 2 received:", value)
}

signal.connect(slot1)
signal.connect(slot2)
signal.emit(42)
// Output:
// Slot 1 received: 42
// Slot 2 received: 42

Disconnecting Slots

const signal = new Signal()

function slot(value) {
    console.log("This will not be logged")
}

signal.connect(slot)
signal.disconnect(slot)
signal.emit("Test")
// No output, as the slot has been disconnected

Using Signal.fromEvent

const userInput = document.getElementById("nameInput")
const inputChangedSignal = Signal.fromEvent(userInput, "input")

function handleNameChange(value) {
    console.log("New user name:", value)
}

inputChangedSignal.connect(handleNameChange)
// When typing 'John' in the text input, "New user name: John" will be logged

Note: When a signal is connected to a DOM Element and the event occurs, the e.target.value is passed as argument to the connected slots.

Conclusion

The Signal class provides a flexible and straightforward way to implement event-driven communication in your application. By allowing functions and other signals to be connected as slots, you can create complex and decoupled architectures with ease.

Key Points:

  • Use signal.connect(slot) to connect functions or other signals.
  • Emit values using signal.emit(...args).
  • Slots are invoked asynchronously to prevent blocking the main execution thread.
  • Manage connections using signal.disconnect(slot) and signal.disconnect().
  • Check connection status with signal.isConnected().
0.0.8

10 months ago

0.0.7

10 months ago

0.0.5

10 months ago

0.0.4

10 months ago

0.0.3

10 months ago

0.0.2

10 months ago

0.0.1

10 months ago