This is called an Event Bus, and it is a very useful way to decouple your code when you don't want each AJAX post (or any other action for that matter) to have to explicitly state what has to happen as a result.
// We've consolidated this functionality in an event manager, which gives us more power
// to log and recover from errors in event handlers.
EventManager.subscribe('ContentAdded', function(e) {
// color every other row whenever content is added to the DOM.
$('table.grid>tbody>tr:nth-child(even)', e.Content).addClass('even-row');
});
Note how I can publish this event anywhere I want in code, and none of those places need to be aware of this code at all. I can also handle the event anywhere else I want, without being tightly coupled to the publishing code.
On the (ASP.NET MVC) project I work on, we have found this to be such an effective approach that we have almost eliminated any other kind of AJAX calls. We've got our event-driven framework to the point where most of our AJAX links use a single, global callback handler that simply publishes whatever events are returned from the server. Any modules that are interested in being notified when specific events occur can subscribe to these events globally.
I might create a link using code like this:
@Html.EventAction("Create Task", "CreateTask")
... which my framework can render as HTML like this:
<a href="/.../CreateTask" data-ajax="true" data-ajax-success="EventHandlers.Success">
Create Task
</a>
When the user clicks this link, it is hijacked to perform an AJAX request to an action like this:
public ActionResult CreateTask()
{
if(!UserCanCreateTasks())
return Events.ErrorResult("You don't have rights to create tasks.");
Events.OpenModalDialog("Create Task", "TaskEditView", new TaskEditViewModel());
return Events.Result();
}
This would in turn generate a JSON object with a ModalDialogOpenedEvent
, which includes the rendered contents of the dialog.
The EventHandlers.Success
method will simply publish all the events that come back, indirectly causing a handler like this to be invoked:
EventManager.subscribe('ModalDialogOpenedEvent', function(e) {
createDialog(e.Title, e.Contents);
});
So our controlling logic can actually stay in our controller, and we have dramatically reduced the amount of custom javascript that we need to write for a given piece of functionality. We no longer need to write custom handler code for each type of button in our UI, and we don't have to worry about what happens when the server returns a response we didn't expect.
For example, if the user's session has timed out, the action code won't even get invoked: the server will immediately redirect the AJAX request to a login handler. We've written the login handler to be smart enough to detect if it's in an event-driven AJAX request and return an event that causes a login dialog to be opened. The request that the user was trying to make gets saved until the server returns an event to indicate that the login succeeded, and then it automatically gets retried. You can imagine how much extra code this would require if every AJAX request in our system had to be ready to handle this sort of corner case. But with an event-based system, it's a breeze.
Best Answer
Just leave out the
event
keyword, instead ofuse just standard delegates (in C#, delegates are multicast enabled). Declare it like this:
Now, for introducing priorities, use something like a priority queue. As a simple form, you can utilize a dictionary:
where the dictionary keys are the different priorities. This dictionary serves as an "event" in the class where you define it. To add some new event handler, you need something like this:
To raise the events in low-prio-first order, you need some code like this: