- Home
- Articles
- Best Practices
- Flash Remoting Best Practices

Broadcasters
Copyright © 2003 O'Reilly Media, Inc. All Rights Reserved. | ![]() |
| This content is excerpted from the above-named O'Reilly publication, with permission, by agreement with ActionScript.org. | |
A broadcaster is based on the Observer pattern, another standard design pattern in programming. A broadcaster is implemented in ActionScript using the undocumented ASBroadcaster class. With this class, you can create objects that broadcast custom events inside your movie. After an event is broadcast, a listener that is listening for that particular event will respond.
WARNING ASBroadcaster is an undocumented class, and, as such, it may not remain in the language forever. You can implement the example here using ASBroadcaster or one of the numerous substitute broadcasters freely available on the Web.
Broadcasters fit right into the Flash Remoting framework because of the asynchronous nature of the technology. When you call a remote service, you don't wait for the response. The remote service method eventually returns a result to the responder function in the Flash client. The remote service is essentially a broadcaster, and your responder object is essentially a listener. This does not provide enough flexibility in handling results, however, so it makes sense to set up a custom broadcaster to convey the remote response to the part of your Flash movie that will benefit from it.
You can set up a broadcaster inside of your responder to broadcast a custom event to the movie. The advantage of this approach is that, once the event is broadcast, you can have one or more listeners acting on the remote response. To create a broadcaster, pass an instance of the generic Object class to the static ASBroadcaster.initialize( ) method:
var myBroadcaster = new Object( );
ASBroadcaster.initialize(myBroadcaster);
This converts myBroadcaster into an
ASBroadcaster object capable of broadcasting.
Specify the custom event to broadcast using the
broadcastMessage( ) method:
myBroadcaster.broadcastMessage("onMyCustomEvent", "Hello there");
Finally, set up a listener object to listen for the custom event.
Here, we create an object, myListener, with an
anonymous function assigned to the onMyCustomEvent
property:
myListener = {
onMyCustomEvent:function(message) {
trace(message);
}
}
Finally, add the listener to the object to
myBroadcaster using the addListener(
) method:
myBroadcaster.addListener(myListener);
Example 12-4 utilizes a broadcaster to broadcast the onResult event from the server, rather than using a callback function. It uses the same HelloUserClass class as shown earlier in HelloUserOOP.fla, with no changes. The only changes are in the ActionScript code in the movie, as well as the two classes that were set up.
Create a copy of the User.as file and rename it UserBroadcaster.as. Change the constructor and the sayHello( ) method as show in Example 12-4 (changes shown in bold).
Example 12-4. UserBroadcaster class
/*
User class
* public UserBroadcaster
constructor:
new UserBroadcaster( ); // Default user with no arguments
new UserBroadcaster(name); // Set a default name property
arguments:
name: string
properties:
service: the remote service with which the user interacts
name: the name of the user
methods:
getName: retrieve name property
setName: set name property
arguments:
name: string
getService: retrieve service object
setService: set the remote service for the object
arguments:
connection: a NetConnection object
servicePath: a path to a remote service
sayHello:interface to remote method, sayHello( )
arguments:
none
Dependencies:
com.oreilly.frdg.BroadcasterResponder
*/
#include "com/oreilly/frdg/BroadcasterResponder.as"
function UserBroadcaster (name) {
if (arguments)
this.name = name;
// Set this class up as a broadcaster
ASBroadcaster.initialize(this);
}
UserBroadcaster.prototype.getName = function ( ) {
return this.name;
};
// Set the name property only if the argument exists and is not blank
UserBroadcaster.prototype.setName = function (name) {
if (name != "" && name != undefined)
this.name = name;
};
UserBroadcaster.prototype.getService = function ( ) {
return this.service;
};
// Create remote service object as a property of User
UserBroadcaster.prototype.setService = function (connection, servicePath) {
this.service = connection.getService(servicePath);
};
UserBroadcaster.prototype.sayHello = function ( ) {
this.getService( ).sayHello(new BroadcasterResponder("onSayHello", this),
this.name);
};
Let's compare the
UserBroadcaster class in Example 12-4 with the User class from
the earlier callback implementation. The main differences are the
initialization of the class as an ASBroadcaster
in the constructor and the fact that the sayHello(
) method now uses a different responder object:
BroadcasterResponder. You pass a custom event
("onSayHello") and the broadcaster object
(this) to the responder function. The responder
object notifies any listeners. The
BroadcasterResponder responder
function's definition is shown here:
/*
public BroadcasterResponder
constructor:
new BroadcasterResponder(event);
arguments:
event: the event that will be broadcast
properties:
none
methods:
onResult: method to handle remote results
arguments:
event: the event that will be broadcast
onStatus: method to handle remote errors
arguments:
event: the event that the error occurred in
Dependencies:
none
*/
function BroadcasterResponder (event, broadcaster) {
this.event = event;
this.broadcaster = broadcaster;
}
// Set up <em>onResult( )</em> and <em>onStatus( )</em> handlers as
// methods of the <em>BroadcasterResponder</em> class
BroadcasterResponder.prototype.onResult = function (myResults) {
this.broadcaster.broadcastMessage(this.event, myResults);
};
BroadcasterResponder.prototype.onStatus = function (myError) {
this.broadcaster.broadcastMessage(this.event + 'Error', myError);
};
System.onStatus = BroadcasterResponder.prototype.onStatus;
The BroadcasterResponder function accepts two
arguments: the custom event that will fire when
this responder is called, and the broadcaster that
will broadcast the message (the UserBroadcaster
object instance, in this case). The implementation is simple: when a
successful result is returned from the server, the
onResult( ) method is called and the broadcaster
broadcasts the event ("onSayHello" in this case)
and the actual results from the remote call to the movie. If an error
is received by the onStatus( ) event handler,
the name of the event becomes event+ "Error", or
"onSayHelloError" in this case. Next, listeners
need to be set up in the main movie:
#include "com/oreilly/frdg/UserBroadcaster.as"
if (initialized == undefined) {
initialized = true;
_global.app = new HelloUserClass("http://localhost/flashservices/gateway");
var servicePath = "com.oreilly.frdg.HelloUser";
app.myUser = new UserBroadcaster("User");
app.myUser.setService(app._conn, servicePath);
}
submit_pb.onRelease = function ( ) {
app.myUser.setName(userName_txt.text);
app.myUser.sayHello( );
};
// Listener object for the <em>onSayHello</em> event
results_txt.onSayHello = function (message) {
this.text = message;
};
// Listener object for errors in <em>onSayHello</em>
results_txt.onSayHelloError = function (message) {
this.text = message.description;
};
app.myUser.addListener(results_txt);
The listener object is the results_txt TextField.
Any object can serve as a listener, but the object must have a
function set up to respond to your custom event. We simply create the
necessary event handlers on the object (by setting the
onSayHello and onSayHelloError
properties to anonymous functions) and then add it as a listener to
receive events fired off by the UserBroadcaster
instance (app.myUser).
Again, this technique is well suited to Flash Remoting. The Macromedia Pet Market blueprint application also uses custom broadcasters. One advantage, as mentioned earlier, is that you can add multiple listeners to the event. For example, you can add this code to create a built-in debugging listener:
var debug = true;
// var debug = false; // Uncomment this line to turn off debugging
var debugListener = {onSayHello:function(message) {
trace("User name: " + app.myUser.getName( ));
trace("Results from server: " + message);
}}
if (debug) app.myUser.addListener(debugListener);
The listener is "turned on" when
the debug flag is set to true. Doing this, you can
add listeners to all of your remote calls without having to dig into
your code to make changes and put trace( )
statements all over the place. It can all be done from one place,
because your listener is listening for the event.
Mixing Procedural and Object-Oriented Code
Another common way to build an application is to mix procedural style with some OOP concepts. ActionScript 1.0 makes it easy to program in this way by not forcing the rules of OOP on you, as some other languages, such as ActionScript 2.0, require. The procedural example shown earlier could easily benefit from some of the techniques shown in the sections about OOP. For example, the code could implement callback functions in a custom responder object or a broadcaster. Chapter 14 shows a complete Flash MX application that is built procedurally using OOP concepts.

