使用ActionScript 3加载和返回文本数据(URLLoader)

时间:2009-12-12 18:34:00

标签: actionscript-3 urlloader

我正在尝试做一些非常简单的事情:编写一个从文本文件中读取文本的函数,并使用AS3以字符串形式返回文本。

功能

    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)
        }
        trace(dataSet);
        return dataSet;
    }

调用函数

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

此代码在运行时返回空字符串。为什么呢?

修改 好的,我现在看到这不起作用,因为urlLoader是异步操作的。我正在编写一个读取数据文件并对其进行操作的程序。这是否意味着我需要在function urlLoader_complete内编写我的其余程序?或者我应该暂停程序直到urlLoader完成?

2 个答案:

答案 0 :(得分:3)

在Flash和Flex中,所有网络I / O都是异步的。必须采用这种方式才能避免阻止浏览器。

因此,无法编写直接返回网络读取操作结果的readData()函数。您必须将回调函数传递给readData()函数。当readData()读完数据后,它可以调用回调函数。

例如:

/**
 * 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);
    }
}

以下是您可以从Flex调用该函数的方法:

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

答案 1 :(得分:1)

3年前,这个问题出现在你面前,但是几个小时前我偶然发现了这个问题,并设法让它发挥作用,并想到为什么不分享它。可能已经有了更好的替代方案,但是嘿,我刚刚开始编写Actionscript,所以没有责备:)

首先使用filecounter构建一个Preloader类。构造函数中将有一个numFiles参数,用于保存要加载的文件总数。每次调用complete方法时,都会添加1到filecounter,并且语句将检查是否所有文件都已加载。当numFiles等于计数器时,调用调用类的start()方法。

* 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++;
            }
        }
    }
}

调用类中的构造函数方法必须调用所有preload文件,start方法将替换构造函数。请注意,当预加载器加载时,需要引用其调用类和“要加载”文件的总数:

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
        }

    }
}