Using the Observer¶
The Observer class is a simple implementation of an observer pattern, which 
allows you to implement synchronous in-process events for a local service. It 
works full stack on every JavaScript system.
To use the Observer class, you will need to import it in your code:
import { Observer } from "./src/fi/hg/core/Observer";
You can then create an Observer instance by calling the constructor and 
passing in a name for the observer:
enum FooEvent {
    CHANGED = "FooService:changed",
}
const observer = new Observer<FooEvent>("MyObserver");
The Observer class provides several methods that you can use to listen for and
trigger events:
listenEvent¶
The listenEvent method allows you to start listening for a specific event. It
takes two arguments: the name of the event to listen for, and a callback 
function that will be called when the event is triggered. It returns a 
destructor function that you can use to stop listening for the event.
Here is an example of how to use the listenEvent method:
const destructor = observer.listenEvent('my-event', (eventName) => {
    console.log(`Event ${eventName} was triggered!`);
});
triggerEvent¶
The triggerEvent method allows you to trigger an event that you have 
previously registered to listen for using the listenEvent method. It takes one
argument: the name of the event to trigger. Any additional arguments passed to 
the triggerEvent method will be passed on to the callback function when the
event is triggered.
Here is an example of how to use the triggerEvent method:
observer.triggerEvent('my-event', 'some data');
waitForEvent¶
The waitForEvent method returns a Promise that is resolved when the specified 
event is triggered. It takes two arguments: the name of the event to wait for,
and the maximum amount of time (in milliseconds) to wait for the event before 
timing out. If the event is not triggered within the specified timeout, the 
Promise is rejected with a timeout error.
Here is an example of how to use the waitForEvent method:
const eventPromise = observer.waitForEvent('my-event', 100);
destroy¶
The destroy method destroys the observer data and stops you from using the 
Observer instance. You should call the destroy method when you no longer 
need the Observer instance, to free up memory and prevent potential memory 
leaks.
Here is an example of how to use the destroy method:
observer.destroy();
Using the Observer with a service¶
To use the Observer class with a service, you can create a class that has an Observer instance as a static property. You can then create methods on the class that allow you to listen for and trigger events, as well as access any data that the service is managing.
Here is an example of how to use the Observer class with a service:
import Observer from "./src/fi/hg/core/Observer";
enum FooEvent {
    CHANGED = "FooService:changed",
}
class FooService {
    private static _data: any;
    private static _observer: Observer<FooEvent> = new Observer<FooEvent>("FooService");
    public static getData(): any {
        return this._data;
    }
    public static on(name: FooEvent, callback: ObserverCallback<FooEvent>): ObserverDestructor {
        return this._observer.listenEvent(name, callback);
    }
    public static refreshData() {
        HttpService.doSomething()
            .then((response) => {
                this._data = response.data;
                this._observer.triggerEvent(FooEvent.CHANGED);
            })
            .catch((err) => {
                console.error("Error: ", err);
            });
    }
}
FooService.on(FooEvent.CHANGED, () => {
    const currentData = FooService.getData();
    // ...
});
FooService.refreshData();
In this example, the FooService class has a static _observer property of 
type Observer<FooEvent>, which is initialized with the name "FooService". The
class has a getData method that returns the current data managed by the 
service, and an on method that allows you to listen for events.
The refreshData method is used to update the data managed by the service and 
trigger the CHANGED event. To listen for the CHANGED event, you can call the
on method and pass in a callback function. When the CHANGED event is 
triggered, the callback function will be called with the event name as its first 
argument.
You can then use the FooService class by calling the on method to listen for 
events and the refreshData method to trigger events and update the data.