views:

333

answers:

6

I've written C++ event-driven apps using MFC for GUI buttons, and I use HTML events like onmousedown to trigger some Javascript in a webpage. The idea of event-driven programming is intuitive when you are using the interface and events are hard-coded.

I know how to use a function pointer in C, and I see how Windows uses them to run an event loop. I can write code to dynamically call a different function.

My problem is, moving away from compile-time and into runtime. I'm talking any language here, but if you need a language, choose Javascript, or PHP as I use them most these days. I don't have a grasp at all of how I might use my own event object to get something done. It's just not a concept I get. And since I don't use them, I don't know what their practical use might be.

For example, I suppose that if I wanted to make a custom turn-based game, that I might use event objects to represent an effect of some game-piece ability that just needs to "happen."

Can someone give me a simple use of custom events? Or situations where it is useful or practical? Does it depend largely on the language and environment and how events are handled? A Javascript answer would be good, but I read many languages.

Sorry I am just deficient in this regard and need some practical, advanced (intermediate?) insight. It's like pointers in C. I "get" pointers and how they are your friend. But there was a time where I didn't, and many people I know still don't. It's simple once you get it, I just don't get custom, dynamic events that way.

A: 

I don't know if I totally understand your question but a class with an event is just like an GUI with a button. Just think about it like a homonculus...Inside every class with an event there's a little person with a virtual button to press. He doesn't know what the button will do, but he knows when to press it. Now think of a related class with another little person in it. That person knows that when he hears a message that a button was pressed, he's supposed to do something.

Anytime you want the second guy to know about something the first guy did, you connect the switchboard between the first class and the second class (Subscribe to the event). When the first guy presses the button (fires the event), the second guy does whatever he knows he's supposed to do...

I don't know if this helps or I'm just on an acid trip thinking of little tiny people in my programs...

Jason Punyon
A: 

At StackOverflow, when you vote down, your reputation falls and your down arrow turns red.

Usually, you write a single onclick, update all elements in it, and try not to forget to change it every time when page layout changes.

Instead, you may declare onVoteDown event, fire it in onclick and subscribe to this event:

  • your reputation div
  • your arrow img
  • your XmlHTTPRequest that sends your vote to the server.
Quassnoi
A: 

I'm not entirely sure what sort of answer you're looking for, so I apologize if this isn't anything close. ;)


By custom, do you mean custom actions, custom triggers, or truly custom events?

E.g.: A custom action would respond to a pre-defined event (say, a mouse click), a custom trigger would be faking a mouse click via script, and a custom event would be a listener that's not defined by the language or isn't readily available.

If you're looking for custom events, I can't really help you. Though, I don't think there's much support for them in JavaScript.


To define an Action...

Events are normally established via pre-defined properties of an object, say window.onload. By default, they are all equal to undefined or null. So, to put them to use, you have to set them to the value of a function.

You can use an "anonymous" function:

window.onload = function (eventObject) {
    /* ... */
};

Or set them to a function reference (not the same, but similar to a pointer):

function handleOnload(eventObject) {
    /* ... */
}

window.onload = handleOnload; /* note the lack of parenthesis */

When the event is triggered, the function is called. So, in either setup, when the page finishes loading, the code you place instead of /* ... */ will be executed.

There's also more formal methods available for creating events. W3C defines addEventListener while IE uses attachEvent. More info.

There are plenty of references available for learning the list of available events. Here's 2 that should give you a good base:


The browser usually handles the triggering of events -- either for browser events (onload) or user events (onclick). The property and function are meant to respond.

Triggering your own event isn't the easiest thing to accomplish. To completely define an Event object takes some work -- and varies between browsers.

Though, if you don't need the Event object, you can simply call the event:

window.onload();
Jonathan Lonowski
+2  A: 

In a compiled langauge, you write your own event loop. In a runtime language, it's implemented by the host environment already, and the programmer only gets an abstracted interface into the events system. You never see the event loop.

There's two facets to building functionality with events. The first is defining the conditions under which an event will fire. In javascript in a browser, there isn't a single "mousedown" event. There's in fact one for every element on the page. In this case, the condition for when any of them will fire is based both on the location of the mouse cursor, and whether the mouse button has just switched from the up state to the down state. This condition may cause multiple events to fire. (In the browser, there's something called event "bubbling" that's related to this. but that's out of scope here).

The other facet is the event handler. An event happens regardless of whether there's a handler for it or not. Providing the handler is up to you. In javascript, functions are first class values. They get defined at runtime, not at compile time- So there's no need for pointers or jump tables. You create a new function at run time, and you assign it to a special property that the host environment looks up when a particular event fires.

so on stack overflow, there will be an event handler on each of the down arrow's "onclick" events, which turns the arrow red, decrements a number, checks some other variable and conditionally shows a notification. Then when the handler returns- it returns control of the thread to the browser, and hallelujah the user can interact with the browser again. (all interactions cease while an event is handled, so you'd better make it quick). Here's an example using the jquery library.

jQuery("a .downarrow")
.click(function(e){ e.target.style.color="red" /* ... do other things */ });

or in raw javascript (version 1.6) it may be

Array.prototype.slice.apply(document.getElementsByTagName("a"))
.filter(function(o){ return !!(/downarrow/).exec(o.className)})
.forEach(function(o){ 
    o.onclick= function(e){ 
        e.target.style.color="red" /* ...do other things * / 
    }
 });

It really is that simple. The main reason you would do something like this is it allows asynchronous interaction. A gui application doesn't progress in a straight line, step by step. It has to respond dynamically to the user's input. Events are a way to kind of fake the appearance of a multithreaded application. It can look to the user that many things are happening simultaneously without interrupting eachother.

You could use a library to define a custom event. This would perhaps encode some domain specific event. For example: you have a chess game that is thinking about its next move. the process for searching for the move runs out of time. The chess game could fire a "onComputerMove" event. You could handle that event with a function that grabs the specifications for the move, and updates the visual representation of the chessboard, and pops up a message for the user, and exits. Then when the player moves you can fire a "onPlayerMove" event, which does much of the same thing.

Breton
+1  A: 

The most wonderful thing about events is that is reduce bidirectional explicit coupling between two modules or classes.

So let say I have two classes: Baby and Mommy


Without events, I roughly see two methods to allow a Mommy to feed a Baby:

  • mommy calls the baby.pokeBelly() method on the Baby each half hour to know if you have to call baby.fillWith(milk).
    The problem is that Mommy's thread have to wait all day after the baby in a while loop
  • Baby know its associated Mommy and call a mommy.feed(me) method, which in turn calls baby.fillWith(milk).
    The problem is then that ask a simple baby to ask the right mommy to fill its belly.
    Babies don't do that as they should stay simple.


With events, you could bind a Mommy.OnBabyCries(baby) to its babie's baby.Cry event:

void Mommy.OnBabyCries(baby) {
    baby.fillWith(milk)
}

After this, if baby wants to eat, all it has to do is raise its Cry event.

The logic stays in the Mommy, or even later in any Babysitter, and Baby stays happy, without having to worry.

total
+1 for the nice baby example :)
Waleed Eissa
+3  A: 

When we talk about event-oriented programming, we're usually talking about one or more implementations of the observer design pattern. And one goal of the observer design pattern is to achieve loose coupling between objects.

That probably doesn't mean much without a good example, and there are certainly lots of good ones out there; I doubt mine will be the best of them, but I'll take a whack at it nonetheless. Imagine two objects. One object wants to know when something happens with the other object, so it can do something itself -- maybe the family dog, Rover, wants to greet Dad at the door when he gets home from work. There are a couple of ways you might program that scenario, right?

  • Make sure Dad has an reference to Rover, and when he comes home, call Rover's greetDatAtTheDoor() method, or

  • Give Rover a reference to dad, listen for Dad's onArriveHome event, and when it fires, call greetDadAtTheDoor() internally.

On the surface, there might not seem to be much difference between the two, but actually, Dad has some of Rover's implementation burned into him; if Rover's implementation had to change for some reason, we'd have to make changes in two places: once in Rover, and then again in Dad. Not a huge deal, maybe, but still, not ideal.

Now imagine Mom wants to greet Dad as well. And the cat, Mr. Bigglesworth, who doesn't like Dad very much, wants to make sure he's not around, so he'd rather go outside. And a neighbor, Joe, wants to know when Dad gets home, so he can bug him about that twenty bucks Dad owes him. How do we account for all those scenarios, and the additional ones that'll inevitably crop up? Placing references to Mom's greetHusband() method, the cat's getOutNow() method, the dog's greetDadAtTheDoor() method, and Joe's goGetMyMoney() method into Dad's class definition would mess things up fast for Dad -- and for no good reason, since all Dad really needs to do, himself, is come home. Mom, the dog, the cat, and the neighbor just want to be notified when that happens, so they can do whatever their internal implementations require.

Languages handle the specifics of this stuff in different ways, but as you'll see when you start Googling around, the pattern usually involves there being an array, or array-like structure, on the event "dispatcher" (in this case, Dad -- i.e., the object everyone else is interested in), and the "subscribers" (e.g., Mom, the cat, Rover, and Joe) all "register" by calling a publicly exposed method on the dispatcher and passing in references to themselves -- references that end up, in some form, in Dad's array of "subscribers." Then, when Dad comes home, he "dispatches" an event -- the "I'm home!" event, say -- which is essentially a function that loops over each of his subscribers and invokes them with some publicly accessible method of their own -- only it's a method whose name Dad doesn't know, doesn't have to know, because the listener provided it when he/she/it passed it in.

Since I happen to code mostly ActionScript these days, here's how it might look in my world -- say, as declared from within my Mom class:

var dad:Dad = new Dad();
dad.addEventListener(DadEvent.ARRIVED_HOME, greetHusbandAtDoor);

private function greetHusbandAtDoor(event:DadEvent):void
{
   // Go greet my husband
}

In Dad, then, all I have to do, when I come home, is:

dispatchEvent(new DadEvent(DadEvent.ARRIVED_HOME));

... and because Flash handles the event-dispatching and notification details for me (again, everyone does it a bit differently, but internally, Flash follows the conceptual model I've described), my Dad comes home, and each family member does what it signed up to do automatically.

Hopefully that explains things a bit -- what event-thinking looks like, what loose coupling means, why it's important, and so on. Best of luck!

Christian Nunciato
Great conceptual answer, while being practical too! In OOD, i've run into trying to make "dumb" objects that only know the bare minimum of info they need, instead of omniscient webs of objects tangling up. Thank you for the design pattern explanation, very insightful for me.
tkotitan