'chain' a series of functions together in actionscript 3

邮差的信 提交于 2019-12-11 01:45:28

问题


I'm calling a function and adding a listener for when the function returns some data. when the data is returned i need to call another function and so on.

Is there an easy way to 'chain' these functions together so that the first one fires - waits for the listener then fires the second one creating a listener for that and so on until the last one calls a separate function that is defined at the start. It would i suppose work on the same lines as the bulk loader scripts.

I'm envisaging the code working something like this:

var dataLoader:DataLoader = new DataLoader(onAllComplete, onError);

dataLoader.add(getData1, {args1, args2}, listnerType.DATA_LOADED);
dataLoader.add(getData2, {args3, args4}, listnerType.DATA_LOADED);
dataLoader.add(getData3, {args5, args6}, listnerType.DATA_LOADED);

dataLoader.start();

private function onAllComplete(e:Array):void {
  //where e contains an array of all the event results
}
private function onError(e:Event):void {
  //will fire if there are any errors along the way
}

Thanks, Josh


回答1:


I would just do something simple like: (also, this is sorta psuedo code, you'll need the correct error events and stuff)

var numLoaded:int = 0;
var numError:int = 0;
var loadingIndex:int = 0;

var itemsToLoad:Array = ['img1.jpg', 'img2.jpg', 'img3.jpg'];

public function startLoading():void{
     loader.load(itemsToLoad[loadingIndex];
     loader.addEventListener(Event.COMPLETE, completeHandler);
}

public function completeHandler(event:Event):void{
     loadingIndex++;
     numLoaded++;
     if(numLoaded + numError >= itemsToLoad.length){
          onAllItemsComplete();
     }else{
          loader.load(itemsToLoad[loadingIndex];
     }
}

public function errorHandler(event:Event):void{
     loadingIndex++;
     numError++;
     if(numLoaded + numError >= itemsToLoad.length){
          onAllItemsComplete();
     }else{
        loader.load(itemsToLoad[loadingIndex]; 
     }
}



回答2:


Been there, done that. Here's the AS3 code:

package com.vpg.rns.util {

    public class AsynchIterator {
        private var iteratorPosition:int;
        private var iterableObjects:Array;
        private var onApply:Function;
        private var onComplete:Function;
        private var done:Boolean;

        public function get position() { return iteratorPosition; }

        public function get isDone() { return done; }

        public function get size() { return iterableObjects.length; }

        /** Create an iterator that will call the given function repeatCall once for each object in iterableObjects, before finally calling completeCall once at the end.
         * The calls will be made asynchronously, with event handlers used to stitch it all together.
         *
         * @param iterableObjects ....... Every object in this array will be passed as the first argument to repeatCall, in order.
         * @param repeatCall ............ This function will be called once for each object in iterableObjects. Its signature is repeatCall(Object, Function).
         * @param completeCall .......... Called once after every item in the array has been processed.
         *
         *
         */
        public function AsynchIterator(iterableObjects:Array, repeatCall:Function, completeCall:Function) {
            this.iteratorPosition = 0; 
            this.iterableObjects = iterableObjects;
            this.onApply = repeatCall;
            this.onComplete = completeCall;
            this.done = false;
        }

        public function iterate():void {
            doNext();
        }

        private function doNext() {
            if (isDone) {
                // Do nothing - already called onComplete. 
            }
            else if (position == size) { 
                done = true;
                onComplete();
            }
            else {
                var obj:Object = iterableObjects[iteratorPosition++];
                onApply(obj, doNext);
            }
        }

    }

}

Obviously, you will want to add an error handler function, keep track of which failed and succeeded, add options for fast-fail versus do-all-you-can, etc.

  • Paul



回答3:


I might be misunderstanding your intentions, but from what you described, you can chain them when the handlers are called... like: Did you want to do something like this but with more condensed syntax?

private function onComplete1(event:Event):void
{
    dataLoader.removeEventListener("onComplete", onComplete1);
    dataLoader.addEventListener("onComplete", onComplete2);

    ... // process event

    dataLoader.load(); // I don't remember the exact calls...
}

private function onComplete2(event:Event)void
{
    dataLoader.removeEventListener("onComplete", onComplete1);
    dataLoader.addEventListener("onComplete", onComplete2);

    ... // process event

    dataLoader.load(); // I don't remember the exact calls...
}



回答4:


That interface looks good to me. The implementation depends on how the functions return their data. AS3 does not support threads, so you have to write your getData() functions to run asynchronously. If you're loading data from a remote site or something this is easy, just use the built-in loader functions, use getBytesLoaded() to tell when they're done, and call your OnComplete callback when everyone's loaded.

If you're just doing a really long computation, you're going to have to break it up. Something like:

class Computation {
    function Step() {/* ... */}
    function IsFinished() {/* ... */}
    function GetResult() {/* ... */}
}

Subclass something like that for each kind of computation you need to do, then pass instances into your data loader. Have them Step() once per frame, and call the OnComplete callback when they're all finished.




回答5:


splinklibrary contains classes that deal with chained asyncronous operations quite nicely.



来源:https://stackoverflow.com/questions/1033314/chain-a-series-of-functions-together-in-actionscript-3

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!