Tuesday, April 19, 2011

Synchronize asynchronous unordered events in JavaScript

At Ovea, we are developing web applications in an Event-Driven way by using an asynchronous communication library plus an local/remote EventBus system we open-sourced.

The EventBus system enables components to publish and subscribe to events like this:

bus.topic('/event/dom/loaded').subscribe(function() {
    // dom loaded
});
bus.topic('/event/member/loaded').subscribe(function(member) {
    // member loaded
});
bus.topic('/event/page/changed').subscribe(function() {
    // page changed
});

Also, we have the usual DOM events, like:

$('#save-info').click(function(e) {
    // button clicked
    return false;
});

when you are working in a component way client-side, components are totally independent and communicate through the Event Bus system. You often need to trigger or do some actions when two or more events have all occurred.

In example, you might need to redraw the UI when the DOM is loaded and when the save-info button has been clicked and when the event '/event/member/loaded' is sent.

With SyncAsync you can do that, and more ! This is a library that can be used to synchronize asynchronous events and trigger some other.

We can write:

var sync = new SyncAsync({
    name: 'test-to-redraw-ui',
    trigger: 'each'
});

jQuery.ready(sync.newCallback());
$('#save-info').click(sync.newCallback(false));
bus.topic('/event/member/loaded').subscribe(sync.newCallback());

sync.sync(function(domReady, save-info, memberLoaded) {
    // Function called when all events are resolved. The function receives all contexts and arguments of all callbacks
    // $ == domReady.arg[0]
    // e == save-info.arg[0] (jQuery event object received by the second callback)
    // Button 'save-info' == save-info.ctx
    // member == memberLoaded.arg[0] 
});

The project is on GitHub at https://github.com/Ovea/js-sync