函数闭包的变量范围?

时间:2014-12-18 03:18:15

标签: actionscript-3 air

我刚刚开始使用嵌套函数,它们非常方便。但是,我遇到了填充变量的问题,该变量稍后由封闭函数返回。

以下代码用于AIR项目加载一些BitmapData。我希望我的变量(" bitmapData")将填充在loaderComplete函数中,但它总是返回为null。但是,在我的跟踪语句中,正在记录图像尺寸,因此很清楚它已被阅读。

我的语法或理解是否有问题(或两者兼而有之; - )

        private function getBitmapData(url:String):BitmapData
        {
            var bitmapData:BitmapData;
            var bytes:ByteArray = getByteArray(url);
            if (bytes == null){
                trace("bytes null");
                return null;
            }

            var loader:Loader = new Loader();
            loader.loadBytes(bytes);
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderComplete);
            loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorListener);

            function loaderComplete(event:Event):void
            {
                loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loaderComplete);
                loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorListener);
                var loaderInfo:LoaderInfo = LoaderInfo(event.target);
                trace("loader",loaderInfo.width, loaderInfo.height);
                bitmapData = new BitmapData(loaderInfo.width, loaderInfo.height, false, 0xFFFFFF);
                trace("bitmapData.rect", bitmapData.rect);
                bitmapData.draw(loaderInfo.loader);
            }

            function ioErrorListener(event:IOErrorEvent):void
            {
                trace("ioErrorListener", event.errorID);
                loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loaderComplete);
                loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorListener);
            }
            return bitmapData;
        }     

        public function getByteArray(url:String):ByteArray{
            var byteFile:File = new File(url);
            if(byteFile.exists && !byteFile.isDirectory){
                var fileStream:FileStream = new FileStream();
                fileStream.open(byteFile, FileMode.READ);
                var tempBytes: ByteArray = new ByteArray();
                fileStream.readBytes( tempBytes );
                fileStream.close(); 
                return tempBytes;
            } else {
                trace("file doesnt exist");
                return null;
            }
        }

1 个答案:

答案 0 :(得分:0)

Loader.loadBytes()是一种异步方法。 COMPLETE事件不会在与loadBytes的调用相同的框架中触发。因此,您在bitmapData执行代码之前,实际上是在尝试返回loaderComplete

您可能想尝试使用回调做一些事情。例如,您可以在getBitmapData中将对函数的引用作为参数传递,然后在loaderComplete中调用该函数:

private function getBitmapData(url:String, callback:Function):void
{
    var bitmapData:BitmapData;
    var bytes:ByteArray = getByteArray(url);
    if (bytes == null){
        trace("bytes null");
        callback(null);
    }

    var loader:Loader = new Loader();
    loader.loadBytes(bytes);
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderComplete);
    loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorListener);

    function loaderComplete(event:Event):void
    {
        loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loaderComplete);
        loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorListener);
        var loaderInfo:LoaderInfo = LoaderInfo(event.target);
        trace("loader",loaderInfo.width, loaderInfo.height);
        bitmapData = new BitmapData(loaderInfo.width, loaderInfo.height, false, 0xFFFFFF);
        trace("bitmapData.rect", bitmapData.rect);
        bitmapData.draw(loaderInfo.loader);
        callback(bitmapData)
    }

    function ioErrorListener(event:IOErrorEvent):void
    {
        trace("ioErrorListener", event.errorID);
        loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, loaderComplete);
        loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, ioErrorListener);
    }
}     

private function handleNewBitmapData(bitmapData:BitmapData):void 
{
    trace("handled bitmapData.rect", bitmapData.rect);
}

getBitmapData("[some url]", handleNewBitmapData);