Solved

How do I make a function fire an event on a return, or make the rest of my application pause until this function returns?

Posted on 2009-04-08
16
175 Views
Last Modified: 2013-11-11
Hello all, Actionscript newbie here.

I've got a function that is called when a button is clicked on a panel.  This function will contact a controller class, that in tern contacts a remote object (java servlet) to gather some data from a database.

I've noticed when I make this call, there seems to be no way for the system to "wait" for this entire process to wait until the call is done before it proceeds.  Is there a way to attach an event listener inside of my remote call on the actionscript side, such that when this event occurs, my program can continue on with the populated data?  Essentially what happens now is that the program continues on, and the data loads a few ms later.  I need the program to wait to get this data before proceeding, so I can populate the next form.  Is this a logical way to proceed, or should I look for another solution?

I've attached some code.  Hopefully it makes sense. Thanks all.
//this gets called when the button is pressed

private function TakeTest(event:MouseEvent):void{

if(incompleteList.selectedItem != null){

	questionController.TakeTest(incompleteList.selectedItem as Course);

	//need to figure out how to either pause here, or take the below and    handle it in another function when the TakeTest method finishes it's business.

	questionViewerPanel.enabled = true;

	questionViewerPanel.visible = true;

	questionViewerPanel.includeInLayout = true;

	questionViewerPanel.GetQuestionAndDisplay();

}

}
 

QuestionController.TakeTest is below:
 

public function TakeTest(courseToTake:Course):void{

			

       var ro:RemoteObject = new RemoteObject("questionSvc");

			

       var token:AsyncToken = ro.getQuestionsForCourse(courseToTake.name);

			

	token.addResponder(new ItemResponder(loadQuestions,onFault));

        	

}

		

private function loadQuestions(event:ResultEvent, token: AsyncToken = null) :void{

	for each(var obj:Object in event.result){

                var tObj2:Question = obj as Question;

                		//add item to array collection

                                  loadedQuestions.addItem(tObj2);

        }

        //I'd like to either return something here, back up to my original page, or fire an event here that I can listen out for.

                		

}

Open in new window

0
Comment
Question by:csciguy81
  • 8
  • 8
16 Comments
 
LVL 37

Expert Comment

by:zzynx
ID: 24102045
Flex is all about events.

1) Make your loadQuestions() function throw a custom event (say QUESTIONS_LOADED)
2) Listen for it in your TakeTest function (cf attached code snippet)


All about Custom Events : http://livedocs.adobe.com/flex/3/html/help.html?content=createevents_1.html
private function TakeTest(event:MouseEvent):void{

   if(incompleteList.selectedItem != null){

          questionController.addEventListener(MyEvent.QUESTIONS_LOADED, function():void {

              questionViewerPanel.enabled = true;

              questionViewerPanel.visible = true;

              questionViewerPanel.includeInLayout = true;

              questionViewerPanel.GetQuestionAndDisplay();

          });

          questionController.TakeTest(incompleteList.selectedItem as Course);

   }

}

Open in new window

0
 

Author Comment

by:csciguy81
ID: 24102064
Can anything throw an event?  Even if it's some piece of embedded actionscript that is down inside of a controller?
0
 
LVL 37

Accepted Solution

by:
zzynx earned 500 total points
ID: 24102240
>> Can anything throw an event?
Every class that extends EventDispatcher

As the docs (http://livedocs.adobe.com/flex/3/langref/flash/events/EventDispatcher.html) say:
In general, the easiest way for a user-defined class to gain event dispatching capabilities is to extend EventDispatcher. If this is impossible (that is, if the class is already extending another class), you can instead implement the IEventDispatcher interface, create an EventDispatcher member, and write simple hooks to route calls into the aggregated EventDispatcher.
0
 
LVL 37

Expert Comment

by:zzynx
ID: 24102265
Handling Events: http://learn.adobe.com/wiki/display/Flex/3b.+Handling%20Events
(and press the next button to see the demo)
0
 

Author Comment

by:csciguy81
ID: 24103178
So would my controller then need to extend Event?  The TakeTest function mentioned above lives on a flex component itself (just a simple panel with a button and some text).  The question controller itself is just an actionscript class.  Would that controller class need to extend Event?

The controller itself is nothing more than a collection of functions that provide remote object calls into my web service.
0
 

Author Comment

by:csciguy81
ID: 24103227
Update.  Here is my QuestionEvent class I wrote.  Now, how do I fire this off from inside of a function that lives inside of another class?


package Custom_Events

{

	import flash.events.Event;
 

	public class QuestionEvent extends Event

	{

		

		

		public function QuestionEvent(type:String, 

            isEnabled:Boolean=false) {

                // Call the constructor of the superclass.

                super(type);

    

                // Set the new property.

                this.isEnabled = isEnabled;

        }
 

        // Define static constant.

        public static const QUESTIONS_UNLOADED:String = "questionsUnloaded";

        public static const QUESTIONS_LOADED:String = "questionsLoaded";
 

        // Define a public variable to hold the state of the enable property.

        public var isEnabled:Boolean;
 

        // Override the inherited clone() method.

        override public function clone():Event {

            return new QuestionEvent(type, isEnabled);

        }
 

		

	}

}

Open in new window

0
 

Author Comment

by:csciguy81
ID: 24103257
I threw this inside of my function in the Question Controller that loads the questions.  It's however telling me, "call to a possibly undefined method dispatchEvent." and erroring out.


var questionEventObj:QuestionEvent = new QuestionEvent("questionsLoaded");

						questionEventObj.isEnabled=true;

						dispatchEvent(questionEventObj);

Open in new window

0
 
LVL 37

Expert Comment

by:zzynx
ID: 24104678
Concerning your own event, this is sufficient:

package Custom_Events {
      
      import flash.events.Event;

      public class QuestionEvent extends Event      {

                public static const QUESTIONS_UNLOADED:String = "questionsUnloaded";
                public static const QUESTIONS_LOADED:String = "questionsLoaded";

            public function QuestionEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
                  super(type, bubbles, cancelable);
            }
      }
}

>> So would my controller then need to extend Event?
No, EventDispatcher
>> It's however telling me, "call to a possibly undefined method dispatchEvent."
That's because it doesn't extends EventDispatcher
0
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 37

Expert Comment

by:zzynx
ID: 24104697
So,

public class YourControllerClass extends EventDispatcher {

   ...
   private function loadQuestions(event:ResultEvent, token: AsyncToken = null) :void{
        ...
       dispatchEvent( new QuestionEvent(QuestionEvent.QUESTIONS_LOADED, true /*bubbling*/) );
   }

}

and

private function TakeTest(event:MouseEvent):void{
   if(incompleteList.selectedItem != null){
          questionController.addEventListener(QuestionEvent.QUESTIONS_LOADED, function():void {
              questionViewerPanel.enabled = true;
              questionViewerPanel.visible = true;
              questionViewerPanel.includeInLayout = true;
              questionViewerPanel.GetQuestionAndDisplay();
          });
          questionController.TakeTest(incompleteList.selectedItem as Course);
   }
}
0
 
LVL 37

Expert Comment

by:zzynx
ID: 24106338
Let me make a correction.
The Flex API Doc says: "You are required to override the Event.clone() method in your subclass."
Why it's important to override clone in your custom Event class?
http://manishjethani.com/blog/2008/04/04/why-its-important-to-override-clone-in-your-custom-event-class/
http://www.allmas-tn.com/200810257/always-override-the-clone-method-for-your-custom-events.html
http://michaelangela.wordpress.com/2008/04/03/implement-clone-in-custom-events/
http://life.neophi.com/danielr/2006/06/events_in_flex_2.html

So to avoid problems later on, you'd better add that clone() function to your QuestionEvent class:
package Custom_Events {

      

      import flash.events.Event;
 

      public class QuestionEvent extends Event      {
 

            public static const QUESTIONS_UNLOADED:String = "questionsUnloaded";

            public static const QUESTIONS_LOADED:String = "questionsLoaded";
 

            public function QuestionEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) {

                  super(type, bubbles, cancelable);

            }
 

            override public function clone():Event {

                return new QuestionEvent(type, bubbles, cancelable);

            }

            

      }

}

Open in new window

0
 

Author Comment

by:csciguy81
ID: 24106932
Yeah, I saw in the docs that I needed to implement Clone, so I threw that in there.  Let me modify my QuestionController to extend EventDispatcher and I'll report back.  Thanks for the help so far.  Hopefully I'll be able to close this one out today.
0
 

Author Comment

by:csciguy81
ID: 24107238
Ok, I got something working, but I have one last question here in these regards.

Instead of having the QuestionController add an event listener, can I make the panel itself have one?  The panel in which the "TakeTest" function resides in has a few other functions inside of <mx:Script> tags that are used on the page itself (to control some loading, etc).  

If I say something like:
this.addEventListener(QuestionEvent.QUESTIONS_LOADED, function():void{//etc}
the listener never listens.

The "this", in this case, would be the component itself (Canvas) right?

If I say something like:
questionController.AddEventListener(QuestionEvent.QUESTIONS_LOADED, function():void){//etc}
the listener listens, everything works as expected.

Why is that?
0
 
LVL 37

Expert Comment

by:zzynx
ID: 24107318
>> If I say something like:
>> this.addEventListener(QuestionEvent.QUESTIONS_LOADED, function():void{//etc}
>> the listener never listens.
Well, it listens but it never "hears" something ;o)
By writing that, you listen for this (Canvas, Panel or whatever) to dispatch that kind of event.
But since we wrote our code in a way that the controller performs a dispatchEvent(...) we should listen on that one for the event.

Assume we have two person classes John and Pete.
If in John we perform a yell("Hello world");
then in we could write code like this:

var pete:Pete = new Pete();
pete.addListener(Yell, ....);

We listen for Pete to yell, while it's John we made yell at us. See?
0
 

Author Comment

by:csciguy81
ID: 24107405
Hmm.  Interesting.

I think I might have a somewhat better understanding now.  Thanks for the great help!
0
 

Author Closing Comment

by:csciguy81
ID: 31568248
Great suggestive help.  Thanks a lot.
0
 
LVL 37

Expert Comment

by:zzynx
ID: 24107446
Glad I could help.
Thanx 4 axxepting
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Introduction This article is primarily concerned with ActionScript 3 and generally specific to AVM2.  Most suggestions would apply to ActionScript 2 as well, and I've noted those tips that differ between AS2 and AS3. With the advent of ActionS…
I have been doing hardcore actionscripting for some time; and needless to say I have faced a lot of problems in just understanding others' code rather than understanding what the code executes. A programmer's life can become hell when there are a lo…
The goal of the tutorial is to teach the user how to how to load their YouTube profile onto Flash Media Live Encoder.
The goal of the tutorial is to teach the user how to select the video input device. Make sure you have an input device that in connected and work and recognized by Adobe Flash Media Live Encoder and select it in the “video input” menu.

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

18 Experts available now in Live!

Get 1:1 Help Now