开发者

Loading and Returning Text Data with ActionScript 3 (URLLoader)

开发者 https://www.devze.com 2022-12-14 08:22 出处:网络
I\'m trying to do something exceedingly simple: write a function that reads text from a text file and returns the text in a string using AS3.

I'm trying to do something exceedingly simple: write a function that reads text from a text file and returns the text in a string using AS3.

The Function

    public function readData(path:String):String
    {
        var dataSet:String;

        var urlRequest:URLRequest = new URLRequest(path);
        var urlLoader:URLLoader = new URLLoader();
        urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
        urlLoader.addEventListener(Event.COMPLETE, urlLoader_complete);
        urlLoader.load(urlRequest);

        function urlLoader_complete(evt:Event):void {
            dataSet = urlLoader.data;
            trace(dataSet)
        }
 开发者_如何学C       trace(dataSet);
        return dataSet;
    }

Calling the Function

    var dataString:String = aq.readData("http://example.com/data.txt");
    trace(dataString);

This code returns a null string when I run it. Why?

EDIT: Ok, I now see that this doesn't work because urlLoader is acting asynchronously. I'm writing a program that reads in a data file and acts on it. Does this mean that I need to write the rest of my program inside function urlLoader_complete? Or should I pause the program until urlLoader is finished?


In Flash and Flex, all network I/O is asynchronous. It has to be this way in order to avoid blocking your browser.

As a result, it is not possible to write a readData() function that directly returns the result of a network read operation. You will have to pass a callback function to the readData() function. When readData() has finished reading the data, it can call the callback function.

For example:

/**
 * Asynchronous function to read data as a string. When the data has been read,
 * the callback function is called with the result.
 * 
 * @param path     the URL to read
 * @param callback the function that is called with the result; should take
 *                 one string argument.
 */
public function readData(path:String, callback:Function):void
{
    var dataSet:String;

    var urlRequest:URLRequest = new URLRequest(path);
    var urlLoader:URLLoader = new URLLoader();
    urlLoader.dataFormat = URLLoaderDataFormat.TEXT;
    urlLoader.addEventListener(Event.COMPLETE, urlLoader_complete);
    urlLoader.load(urlRequest);

    function urlLoader_complete(evt:Event):void {
        dataSet = urlLoader.data;
        trace(dataSet);
        callback(dataSet);
    }
}

Here is how you might call that function from Flex:

<mx:Label id="mylabel" />
<mx:Button click="readData('http://www.google.com/',
    function(s:String):void {mylabel.text = s})" />


Its been 3 years ago since this question arose with you, but since I stumbled on this problem a few hours ago, and managed to get it to work and thought why not share it. There might be better alternatives already, but hey I just started coding Actionscript so no blames :)

First build a Preloader class with a filecounter. There will be a numFiles parameter in the constructor which holds the total number of files to be loaded. Every time when the complete method is called, 1 to the filecounter will be added and a statement will be checking if all files are loaded. when the numFiles is equal to the counter call the start() method of the calling class.

*Preloader.as *

package
{
    import flash.display.Loader;
    import flash.events.Event;
    import flash.events.IOErrorEvent;
    import flash.net.URLLoader;
    import flash.net.URLRequest;

    public class Preloader
    {
        public var urlLoader:URLLoader;
        public var response:Array = new Array();
        public var callingClass:Object;
        public var numFiles:uint;
        private var counter:uint;

        public function Preloader(callingClass:Object, numfiles:uint)
        {
            this.callingClass = callingClass;
            this.numFiles = numFiles;
        }

        public function load(name:String):void
        {
            var request:URLRequest = new URLRequest(name);
            urlLoader = new URLLoader();
            urlLoader.addEventListener(Event.COMPLETE, onLoad);
            urlLoader.load(request);
        }

        public function onLoad(event:Event):void
        {
            response[counter] = event.currentTarget.data;
            if(numFiles == counter) {
                callingClass.start();
            } else {
                counter++;
            }
        }
    }
}

The constructor method in the calling class will have to call all the preload files and the start method will be the replacement of your constructor stuff. note that when the preloader loads it need the reference to its calling class and the total number of "to be loaded" files:

package  
{
    import flash.display.MovieClip;
    import misc.Preloader;

    public class Path extends MovieClip
    {
        public var preloader:Preloader = new Preloader(this, 3); //pass this class and the total number of files

        public function Controller()
        {       
            preloader.loadJSON('file1.js');
            preloader.loadJSON('file2.js');
            preloader.loadJSON('file3.js');
        }

        public function start():void
        {
            trace(preloader.response[0]); //Get first file contents
        }

    }
}
0

精彩评论

暂无评论...
验证码 换一张
取 消