Быстрый способ найти функции обратного вызова ... - PullRequest
2 голосов
/ 28 июля 2011

Я привык к более управляемой событиями среде, но копия, над которой я сейчас работаю, дозирует все как обратные вызовы функций. Когда я спросил об этом, один из разработчиков сказал, что это потому, что обратные вызовы быстрее из-за пузырьков, но свойство пузырьков всегда может быть установлено в false ...

Итак, у меня проблема с попыткой выяснить, на какую функцию обратного вызова ссылаются.

Например:

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, get action = Function (@ 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 ]

2 голосов
/ 28 июля 2011

Это невероятно сложный код, но ради этого примера вы можете использовать стек вызовов отладчика:

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;
    }
}
2 голосов
/ 29 июля 2011

Вы можете выдать ошибку в try ... catch, чтобы проверить стек, не убивая приложение. Это решение заставляет меня съеживаться, но в то же время довольно хитро. Первоначально Ральф Бокельберк, но так как его блог в настоящее время не работает , вместо этого я буду ссылаться на , где я его и нашел.

А вот методика в коде для потомков:

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);
}
1 голос
/ 28 июля 2011

Человек, я в одной лодке. Эта база кода огромна и сделана таким же образом. «Посыпать» было бы преуменьшением в моем случае. Если у объекта функции нет обработчика имени функции, вы СОЛ. Один из способов понять мой путь через код - использовать UML для представления этих различных классов и использовать оператор ассоциации, чтобы показать, что это что-то вызывает. Это так легко потеряться, когда обратные вызовы перезванивают другой обратный вызов. Имея UML Diagram, которую вы создаете, это как хлебные крошки, пытающиеся вырваться из кроличьей норы. Через некоторое время к этому привыкаешь. Буду ли я принять этот способ программирования? Черт возьми, нет, они только усложнили работу следующего парня. Я использую Violet UML для отслеживания моего путешествия по обратным вызовам.

...