Event Bus
Let's create an event bus that the entire application can interact with
Like many other programming languages, Vortex will cache module imports, meaning that files get evaluated only once on the first import, and the cached version will be returned on every consecutive import after that.
This allows us to instantiate a single object that can be imported and modified throughout the entire application.
Event Type
We'll begin by defining an Event
type that the event bus can accept:
type Event = (name) => ({
name: name
})
It's pretty bare bones, but we'll use it to make sure that only valid events are passed to the event bus.
Event Bus
We'll now define the event bus constructor:
type EventBus = () => ({
events: {},
addEvent: (e) => {
if (e.info().typename != "Event") {
println(f"${e} is not a valid Event")
return
}
if (this.events[e.name]) {
println(f"Event ${e} is already defined")
return
}
this.events[e.name] = {
event: e,
subscribers: []
}
},
removeEvent: (event_name) => {
this.events.remove_prop(event_name)
},
subscribe: (event_name, callback) => {
if (!this.events[event_name]) {
println(f"No such event \"${event_name}\"")
return
}
this.events[event_name].subscribers.append(callback)
},
unsubscribe: (event_name, callback) => {
if (!this.events[event_name]) {
println(f"No such event \"${event_name}\"")
return
}
for (this.events[event_name].subscribers, index, sub) {
if (sub == callback) {
this.events[event_name].subscribers.remove(index)
break
}
}
},
emit: (event_name, payload = None) => {
if (!this.events[event_name]) {
println(f"No such event \"${event_name}\"")
return
}
const e = this.events[event_name]
for (e.subscribers, index, sub) {
if (sub.info().arity == 0) {
sub()
} else {
sub(payload)
}
}
}
})
The event bus will need to have the ability to store events and their subscribers (really, just callbacks), add new events, remove events, subscribe and unsubscribe callbacks to events and emit events.
Just to make things nice and concise, we'll declare an EventType object that we'll use when subscribing/unsubscribing to events:
var EventType = {
Funds_Added: "funds_added",
Funds_Removed: "funds_removed"
}
Next, we instantiate a global event bus that will be used throughout the entire application, and add two new events to it based on the EventType
we just declared:
const event_bus = EventBus()
event_bus.addEvent(Event(EventType.Funds_Added))
event_bus.addEvent(Event(EventType.Funds_Removed))
That's it, we now have an event bus that we can import in other parts of our application. This event bus has two events that can be subscribed to and emitted. Let's explore an example of that.
In another nested file, we'll import the event_bus and add a new event to it.
We'll also create some callbacks to handle the events and subscribe to them. This is all that this file will do, we'll handle emitting the events in another file.
import [event_bus, EventType, Event] : "../../event_bus"
EventType.Account_Deleted = "account_deleted"
event_bus.addEvent(Event(EventType.Account_Deleted))
var balance = 55.5
const handle_account_deleted = (payload) => {
println("OH NOOOOO")
}
const handle_funds_added = (payload) => {
balance += payload.amount
println(balance)
}
const handle_funds_removed = (payload) => {
balance -= payload.amount
println(balance)
}
event_bus.subscribe(EventType.Funds_Added, handle_funds_added)
event_bus.subscribe(EventType.Funds_Removed, handle_funds_removed)
event_bus.subscribe(EventType.Account_Deleted, handle_account_deleted)
In our main file, we'll also import the other
file we just wrote. This will evaluate it, and add the new event to the bus, as well as handle the subscriptions. We'll then import the same event_bus
and emit those events:
import other : "nested/other"
import [event_bus, EventType] : "../event_bus"
event_bus.emit(EventType.Funds_Added, { amount: 20 })
event_bus.emit(EventType.Funds_Removed, { amount: 13.46 })
event_bus.emit(EventType.Account_Deleted)
This should then go through the list of callbacks and fire them off, producing this output:
75.5
62.04
OH NOOOOO
Last updated