/** * IntervalManager, 提供一组管理 interval 的功能 * * @author kakera * @version 1.0 */ class MirageSystem.utils.IntervalManager extends MirageSystem.core.EventObject { // // 一些状态常量 // public static var RUNNING:Number = 0; public static var STOPPED:Number = 1; public static var PAUSED:Number = 2; // // interval 被 invoke 的事件 // public static var INVOKE:String = "invoke"; public static var STOP:String = "stop"; // // 存放所有 intervals // private static var intervals:Array = new Array(); // // 用于保存变量, 这里为了优化输出 swf 的体积没有做相应的 getter / setter // public var id:Number; public var func:Function; public var interval:Number; public var totalCount:Number; public var scope:Object; public var args:Array; public var delay:Boolean; public var returnVar:String; public var returnScope:Object; public var hasReturnValue:Boolean; public var state:Number; public var intervalId:Number; public var currentCount:Number; /** * 设置一个新的 IntervalManager, 返回 IntervalManager 实例 * * @usage * @param func 要执行的函数 * @param interval 每次执行间隔 * @param args 可选, 传递的参数 * @param delay 可选, 确定首次执行的时间, 0 或者 interval 的时间 * @param count 可选, 运行的间隔 * @param scope 可选, 修改函数的执行范围, 起到 Delegate 的作用 * @param returnValue 可选, 指定存放返回值的变量, 该数组的第 1 个元素是变量的范围, 第 2 个元素是变量的名称 (字符串表示) * @return */ public static function run (func:Function, interval:Number, args:Array, delay:Boolean, count:Number, scope:Object, returnValue:Array):IntervalManager { var intervalMgr = new IntervalManager(func, interval, args, delay, count, scope, returnValue, intervals.length); intervals.push(intervalMgr); return intervalMgr; } /** * 释放所有的 interval * * @usage * @return */ public static function cleanUp ():Void { for (var i in intervals) intervals[i].release(); } private function IntervalManager (func:Function, interval:Number, args:Array, delay:Boolean, count:Number, scope:Object, returnValue:Array, id:Number) { // // 错误检查, 如果觉得多余可以注释掉. 减少文件尺寸 // if (id == undefined) throw new Error("参数 id 不能为空"); // // 根据 returnValue 参数确定该函数是否有返回值 // if (returnValue instanceof Array) { if (returnValue.length != 2) { throw new Error("参数 returnValue 只能是长度为 2 的数组"); } hasReturnValue = true; } else { hasReturnValue = false; } this.func = func; this.interval = interval; this.args = args; this.delay = delay; this.totalCount = count == undefined ? Infinity : count; this.currentCount = 0; this.scope = scope; this.id = id; this.returnScope = returnValue[0] this.returnVar = returnValue[1]; start(); } /** * 开始 interval * * @usage * @return */ public function start ():Void { if (state != PAUSED) { // // 确定首次执行时间 // if (delay) invoke(func); intervalId = setInterval(this, "invoke", interval, func); } setState(RUNNING); } /** * 停止 Interval, 或者可以通过使用 release 来释放 IntervalManager 实例 * * @usage * @return */ public function stop ():Void { //trace("stop()"); // // 重置 currentCount 计数并清除 interval // dispatchEvent( {type : STOP, currentCount : currentCount, totalCount : totalCount} ); currentCount = 0; clearInterval(intervalId); intervalId = 0; setState(STOPPED); } /** * 暂停 interval, 如果已经在暂停中则会恢复 interval * * @usage * @return */ public function pause ():Void { if (state != PAUSED) { setState(PAUSED); } else { this.start(); } } /** * 提供释放 IntervalManager 的功能, 虽然我不知道这么干到底有没有用 -_-, * 如果你觉得不需要可以改掉 * * @usage * @return */ public function release ():Void { //trace("release()"); // // 直接使用 stop() 是调用不到的 -0- // this.stop(); // // 移除数组中关联的 IntervalManager 实例 // intervals.remove(id); // // 如果上面的句子报错, 请注释掉上面的, 并取消注释下面这句 // intervals["remove"](id); // // 或者你可以通过为 Array 类增加一个方法 remove 来解决此问题 // for (var i in this) delete this[i]; } /** * 设置当前状态 * * @usage * @param state * @return */ private function setState (state:Number):Void { this.state = state; } /** * 调用方法的方法 * * @usage * @param method 要调用的方法的引用 * @return */ private function invoke (method:Function):Void { // // 判断 count 是否继续循环, 否则释放循环 // if (totalCount > currentCount) { // // 如果当前状态是暂停中就跳过 // if (state != PAUSED) { currentCount++; // // 广播 INVOKE 事件, 返回当前执行了的次数和总次数 // dispatchEvent( {type : INVOKE, currentCount : currentCount, totalCount : totalCount} ); // // 判断是否有是有返回值的调用 // if (hasReturnValue) { returnScope[returnVar] = method.apply(scope, args); } else { method.apply(scope, args); } } if (totalCount <= currentCount) { release(); } } else { release(); } } }