AS3 Сообщение об ошибке из обратного вызова события - PullRequest
2 голосов
/ 17 августа 2011

Я экспериментировал с предоставлением лучшей отладочной информации, когда ошибка возникает в асинхронном коде в AS3.

В качестве примера плохой отчетности об ошибках по умолчанию, возьмите случай, когда я принудительно устанавливаю нулевой указатель вОбратный вызов таймера ( github gist ), я получаю на консоли следующую трассировку стека:

TypeError: Error #1009: Cannot access a property or method of a null object reference.
    at Function/<anonymous>()[/[path-to-source-file]/TestClass.as:14]
    at flash.utils::Timer/_timerDispatch()
    at flash.utils::Timer/tick()

Это очень мало говорит мне о том, как обратный вызов таймера фактически ссылается на мой код.

Вопрос в том, как я могу получить информацию о том, какой код создал обратный вызов?

Я добавил одно из своих решений ниже.Мне интересно посмотреть, можно ли это улучшить.

Ответы [ 3 ]

0 голосов
/ 17 августа 2011

Интересная вещь.

Документ для Error.getStackTrace() говорит :

Возвращает стек вызовов для ошибки в виде строки во времяконструкция ошибки

В соответствии с этим трассировка стека работает, как и ожидалось.Ошибка создается в вашем обработчике событий, который вызывается тиковым событием timer.

Во втором примере вы создаете ошибку, которая будет отправлена ​​в конструкторе TestClass.Таким образом, ваша трассировка стека покажет цепочку до конструктора TestClass.

0 голосов
/ 18 августа 2011

Вы, вероятно, попросите общее решение.Я бы пошел с юнит-тестами и правильной отладкой, используя точки останова и проверку объектов.Но вот другая идея:

TestClass:

package {
    import flash.events.TimerEvent;
    import flash.utils.Timer;

    public class TestClass {
        public function TestClass(userCallback : Function, fail : Function) {
            var timer : Timer = new Timer(1000, 1);
            timer.addEventListener(TimerEvent.TIMER, internalCallback);
            timer.start();

            function internalCallback(e : TimerEvent):void {
                try {
                    var nullProperty : String;
                    nullProperty.length;
                } catch (e:Error) {
                    fail();
                    return;
                }
                userCallback();
            }
        }
    }
}

Main:

package {
    import flash.display.Sprite;

    public class Main extends Sprite {
        public function Main() {
            new TestClass(
                function() : void { trace('Call me back when your done.'); },
                function() : void { throw new Error('Something went wrong.'); }
            );
        }
    }
}

Выход:

Exception fault: Error: Something went wrong.
    at Function/<anonymous>()[Main.as:8]
    at Function/TestClass/$construct/internalCallback()[TestClass.as:16]
    at flash.utils::Timer/_timerDispatch()
    at flash.utils::Timer/tick()
0 голосов
/ 17 августа 2011

Одним из возможных решений является предварительное создание объекта Error в потребительской «нити» / «scope»

        var errorInConsumerScope:Error = new Error()

        var timer:Timer = new Timer(1000, 1)
        timer.addEventListener(TimerEvent.TIMER, internalCallback)
        timer.start()

        function internalCallback(e:TimerEvent):void 
        {
            try
            {
                // do something that could cause an error
            }
            catch (e:Error)
            {
                errorInConsumerScope.message = e.message
                throw errorInConsumerScope
            }
        }

Теперь это возвращает мне стековую трассировку обратно в мой вызывающий код:

Error: Error #1009: Cannot access a property or method of a null object reference.
    at TestClass()[/[path-to-source-file]/TestClass.as:10]
    at Main()[/[path-to-source-file]/Main.as:9]

Полный смысл здесь

...