快速找到函数回调的方法......

时间:2011-07-28 19:10:33

标签: flash flex flash-builder flexbuilder

我习惯了更多事件驱动的环境,但我现在正在使用的副本将所有内容都作为函数回调。当我问起这个开发人员说这是因为冒泡时回调更快,但冒泡的属性总是可以设置为假...

所以我遇到了试图找出正在引用哪个回调函数的问题。

例如:

public class A {
    public function A(){}
    public function func_1():Number{ return 1; }
    public function func_2():Number{ return 2; }
    public function doSomething:Function{ 
        if( Math.random > 0.5 ) return func_1; else return func_2;
    }
}

然后我可以在B类中运行代码:

public class B{
    public var a:A = new A();
    private var action:Function;
    public function B(){ action = a.doSomenthing(); }
}

所以当我在BI内部设置一个断点时,获取动作=功能(@ 34567)这实际上是完全无用的......我意识到我可以在func_1和func_2中设置一个断点,但我只是将它用作一般的例子,在代码中散布着函数回调...是否有办法通过内存地址获取函数的名称?感谢

我想我看到你对堆栈跟踪的看法。但是你必须在代码中逐步完成该功能。在下面的这个例子中,我必须在callback()上设置一个断点;并跳过它以查看堆栈跟踪更新。问题是我想在调用之前知道回调。有时它们在其他地方被召唤。没有其他方法可以获得回调?

public var callbacks:Array = [];
public function loadURL( url:String, callback:Function ){
    loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
    callbacks.push( callback );
    var request:URLRequest = new URLRequest(url);
    loader.load(request);
}

public function completeHandler( event:Event ):void
{
    for( var i:int = 0; i < callbacks.length; i ++ ){
        var callback:Function = callbacks[i];
        callback();
    }
}

3 个答案:

答案 0 :(得分:2)

这是非常难以置信的代码,但是为了这个例子,您可以使用调试器中的调用堆栈:

enter image description here

您的示例代码存在许多问题,但此捕获是基于对您的实现的轻微调整:

package
{
    import flash.display.Sprite;

    public class MultiCallback extends Sprite
    {
        public function MultiCallback()
        {
            super();

            var b:B = new B();
            b.action()();
        }
    }
}


internal class A
{
    public function A()
    {
    }

    public function func_1():Number
    {
        return 1;
    }

    public function func_2():Number
    {
        return 2;
    }

    public function doSomething():Function
    {
        if (Math.random() > 0.5)
            return func_1;
        else
            return func_2;
    }
}

internal class B
{
    public var a:A = new A();

    public var action:Function;

    public function B()
    {
        action = a.doSomething;
    }
}

答案 1 :(得分:2)

你可以在try ... catch中抛出一个错误,这样你就可以在不杀死应用程序的情况下检查堆栈。这个解决方案让我感到畏缩,但同时又很狡猾。最初由Ralf Bokelberk撰写,但由于他的博客目前不起作用I'll link to here instead,这是我发现它的地方。

以下是后代代码中的技巧:

var stackTrace:String;

try { throw new Error(); }
catch ( e: Error ) { stackTrace = e.getStackTrace(); }

var lines:Array = stackTrace.split('\n');
var isDebug Boolean = (lines[int(1)] as String).indexOf('[') != int(-1);

var path:String;
var line:int = -1;

if (isDebug) {
    var regex:RegExp = /at\x20(.+?)\[(.+?)\]/i;
    var matches:Array = regex.exec(lines[int(2)]);

    path = matches[int(1)];

    //file:line = matches[2]
    line = matches[int(2)].split(':')[int(2)];//windows == 2 because of drive:\
} else {
    path = (lines[int(2)] as String).substring(4);
}

答案 2 :(得分:1)

男子我在同一条船上。这个代码库是巨大的,并以相同的方式完成。在我的案例中,“洒水”将是轻描淡写。如果函数对象没有函数名称处理程序,那么您就是SOL。我理解代码的方法之一是使用UML来表示这些不同的类,并使用关联运算符来显示这是在调用某些东西。当回调回调另一个回调时,它很容易迷失。你制作的UML图就像面包屑,试图让自己脱离兔子洞。过了一会儿,你就习惯了。我会采用这种编程方式吗?不,他们只是让下一个人难以维持。我使用Violet UML来跟踪我在回调中的旅程。