Strongly Typed Events 0.2.0 – now with Simple Events

while ago I started a GitHub project for Strongly Typed Events in TypeScript. I've uploaded the second version (0.2) with support for Simeple Events (ISimpleEvent<TArgs>) and I changed the way you can expose the dispatcher as an event. The code is 100% backwards compatible with version 0.1 - you might need to update some references.

Introducing ISimpleEvent<TArgs>

The IEvent<TSender, TArgs> is modeled after .Net's implementation of the EventHandler. Some projects might not feel comfortable with the sender argument or may prefer to add the sender to the TArgs object or disregard it entirely. That's why I've added the ISimpleEvent<TArgs> to the project. It makes life a little bit easier. Consider the following code:

class ImageDownloader {

    private _ondownload: SimpleEventDispatcher<ImageDownloadArg> 
                                    = new SimpleEventDispatcher();

    public get ondownload(): ISimpleEvent<ImageDownloadArg> {
        return this._ondownload.asEvent();
    }

    public download(url: string, callback?: ISimpleEventHandler<ImageDownloadArg>) {

        let img = new Image();

        img.onload = () => {

            let result = new ImageDownloadArg(url, img.height, img.width);

            if (callback) {
                callback(result);
            }

            this._ondownload.dispatch(result);
        };

        img.src = url;
    }
}

class ImageDownloadArg {

    private _url: string;
    private _height: number;
    private _width: number;

    constructor(url: string, height: number, width: number) {
        this._url = url;
        this._height = height;
        this._width = width;
    }

    public get url(): string {
        return this._url;
    }

    public get height(): number {
        return this._height;
    }

    public get width(): number {
        return this._width;
    }
}

The code uses the same concepts as a IEvent<TSender, TArgs>: a dispatcher and an interface.

Minimizing dispatcher exposure

Another major new feature is a new way to minimize exposure of the dispatcher object. The dispatcher is an easy way to add a single event to a class. In version 0.1 an event could be implemented using the following code:

interface MyEventArgument { }

class MyClass {

    private _myEvent: EventDispatcher<MyClass, MyEventArgument>
                        = new EventDispatcher<MyClass, MyEventArgument>();

    get myEvent(): IEvent<MyClass, MyEventArgument> {
        return this._myEvent;
    }
}

In the TypeScript world, everything is well, but in the JavaScript world we are now exposing our dispatcher. Some JS might now call the dispatch method, which might be very undesirable. That's why the dispatcher now has an asEvent method that will return a wrapped dispatcher that implements the subscribe and unsubscribe methods. In version 0.2 events can be exposed like:

    get myEvent(): IEvent<MyClass, MyEventArgument> {
        return this._myEvent.asEvent();
    }

Asynchronous event execution

Some events might take a while to execute, that's why I added an option to do asynchronous event execution. The code looks like this:

/**
* Dispatches the events thread.
* @param sender The sender.
* @param args The arguments object.
*/
dispatchAsync(sender: TSender, args: TArgs): void {
    for (let handler of this._subscriptions) {
        this.excuteAsync(sender, args, handler);
    }
}

private excuteAsync(sender: TSender, args: TArgs, handler: IEventHandler<TSender, TArgs>): void {
    window.setTimeout(() => handler(sender, args), 0);
}

Using an asynchronous approach is as easy as replacing the calls to dispatch with dispatchAsync.

Documentation

I also improved documentation, both in the TS files (JavaDoc) and in .md form as some "How To's":

expand_less