6 Replies Latest reply on Apr 21, 2008 5:46 PM by pawzlion

    How do I pass data to an event handler ?

    pawzlion
      I'm coding an app in html/javascript that loops through a list of urls and calls URLLoader to load the data from each url, setting up an event listener for each one that runs a function when the complete event triggers for the load. Here is a sample of the code:

      function getData() {
      var request = new air.URLRequest(" http://www.catpa.ws/test.txt");
      var loader = new air.URLLoader();
      loader.addEventListener(air.Event.COMPLETE, saveData);
      loader.load(request);
      }
      function saveData(event) {
      var data = event.target.data;
      // save data as test.txt
      }

      In the saveData function, I want to know the file name that was requested so that I can save the contents of the file to disk, using the same name as the one that was retrieved.

      My problem is, afaik the function that receives an event can only have one parameter, which is the event object. How can I somehow tell the saveData function what the name of the file is to be so that it can save it ? I can't just store the name in a global variable, because I'm going to be launching a whole series of these load commands for each of my urls, and they may not finish in the same order they were started.

      What other way can I pass information to an event listener function ? If I am missing some fundamental technique related to asynchronous programming, I'd really appreciate being clued in.
        • 1. Re: How do I pass data to an event handler ?
          Admiral_Brodnack
          In this case, you could use a closure:

          function getData() {
          var request = new air.URLRequest(" http://www.catpa.ws/test.txt");
          var loader = new air.URLLoader();
          loader.addEventListener(air.Event.COMPLETE, function(event){
          var data = event.target.data;
          // save data as test.txt
          });
          loader.load(request);
          }

          That allows the handler function to use the variables in the getData function.

          Another way to do it would be to create an object that handles the loading and saving. This object would store the relevant file name and since each of your loaded URLs would have its own object, there's no collision of global variables.
          • 2. Re: How do I pass data to an event handler ?
            pawzlion Level 1
            I was unaware of the technique of 'closures' but have discovered a bit about it in my research. I thought I'd share what solution I actually took.

            I read an article about dealing with asynchronous functions in a blocking, or synchronous way. It featured Narrative Javascript and JWACS.

            I tried Narrative Javascript and found it easy to use as it completely solved the problem of starting procedures asynchronously. I loaded the "compiler" (pre-processor) javascript in my header and put my functions inside an external file called functions.njs :

            function getData() {
            var request = new air.URLRequest(" http://www.catpa.ws/test.txt");
            var loader = new air.URLLoader();
            var notifier = new EventNotifier();
            loader.addEventListener(air.Event.COMPLETE, notifier);
            loader.load(request);
            notifier.wait->();
            alert(loader.data);
            }

            I then called the compiler on load with:
            NjsCompiler.load("functions.njs");

            As a result, the code now blocks program execution until the event is caught, but doesn't tie up the AIR environment.


            • 3. How do I pass data to an event handler ?
              pawzlion Level 1
              I have converted my getData function into an object instead and have a medthod like this:

              FileDownload.prototype.download = function() {
              var request = new air.URLRequest(this.url);
              var loader = new air.URLLoader();
              loader.addEventListener(air.Event.COMPLETE, function(event) {
              this.data = event.target.data;
              });
              loader.load(request);
              }


              The problem is, the "this.data = event.target.data" statement inside the closure doesn't work. From within the closure, I cannot read existing or create new properties. It doesn't give any errors or anything - it just doesn't work.
              Curiously I found the same problem with Narrative Javascript - .. after an asynchronous function call's return, you can no longer read/set properties of the object.

              Is this a flaw in such closure techniques, or am I doing something wrong ?
              • 4. Re: How do I pass data to an event handler ?
                duncanhall Level 1
                Not sure about implementing this within javascript, but I have written an AS3 class that allows an infinite number of parameters to be broadcast with any event:

                http://www.kirupa.com/forum/showthread.php?t=291250
                • 5. Re: How do I pass data to an event handler ?
                  Joe ... Ward Level 4
                  One problem may simply be that your variables are defined locally to the scope of the function. Once this function exits, for example, the loader variable is no longer in scope and cannot be accessed. Declare the loader variable outside the function if you need to access it later.

                  The problem with:

                  loader.addEventListener(air.Event.COMPLETE, function(event) {
                  this.data = event.target.data;
                  });

                  Is, most likely, that the "this" object is set to the caller in JavaScript, not to the object to which the function belongs. So in this case "this" refers to the event dispatcher, not FileDownload. The way around this is to set a variable to reference "this" before calling your inner function:

                  FileDownload.prototype.download = function() {
                  var request = new air.URLRequest(this.url);
                  var loader = new air.URLLoader();
                  var that = this;
                  loader.addEventListener(air.Event.COMPLETE, function(event) {
                  that.data = event.target.data;
                  });
                  loader.load(request);
                  }
                  • 6. Re: How do I pass data to an event handler ?
                    pawzlion Level 1
                    Is, most likely, that the "this" object is set to the caller in JavaScript, not to the object to which the function belongs. So in this case "this" refers to the event dispatcher, not FileDownload. The way around this is to set a variable to reference "this" before calling your inner function


                    Oh my god, you're so right ! The worst thing about this is that I read another post where someone tried to explain this very concept to some else, but it wasn't explained well and I didn't understand where the "that = this" statement should go, but you explained it perfectly ! Thanks !