Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Обработка ошибок при асинхронном выполнении кода (http://www.flasher.ru/forum/showthread.php?t=178814)

Mirror13 29.04.2012 19:37

Обработка ошибок при асинхронном выполнении кода
 
Я задавал этот вопрос на двух ресурсах, но он до сих пор без ответа. Но, тем не менее, вопрос интересный. Изначально он касался JavaScript'а, но в целом эта тема так же актуальна и относительно ActionScript'а, я не раз задумывался над этим.

При синхронном выполнении кода исключения — очень удобный механизм обработки ошибок. Но в JavaScript и ActionScript очень много кода, выполняемого асинхронно. Часто для обработки ошибок в этом случае используются коллбэки, но по удобству такая методика не сравнится с исключениями, при которых стек вызовов самостоятельно раскручивается до места перехвата.

Я долго и упорно искал что-то по теме обработки ошибок в JS при асинхронном выполнении, но находил только что-то вроде этого:
Код AS1/AS2:

try {
    helloWorld();
}
catch (e) {
    alert(e.message);
}
 
function helloWorld() {
    throw new Error('Hello world!');
}

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

Есть ли хорошие статьи по поводу обработки ошибок при асинхронном выполнении, особенно в JS или AS3? Может быть, существуют специфические паттерны или малоизвестные возможности этих языков?

Bgg 29.04.2012 19:41

События
Код AS3:

loader.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);


Mirror13 29.04.2012 20:31

Да, это базовое понятие программирования на AS. Но, по сути дела, это тот же коллбэк, который вызывается по событию. Но что делать потом?

Если бы событие могло всплывать по всему стеку вызовов, и генерироваться любым объектом, можно было бы кинуть кастомное событие. Но, насколько мне известно, это не так.

Wolsh 29.04.2012 21:32

Приведите пример асинхронного стека.
try/catch/finally используется только в синхронном коде, незачем обвинять его в непригодности там, где он и не подписывался помогать.
В асинхронном коде используются События, и другого инструмента, кроме естественного, нет.
Асинхронные ошибки могут произойти после вызова асинхронных операций вроде загрузки, коих немного. Обычно (не уверен, что всегда, только потому, что не все еще во флэше перепробовал)) исполнители таких операций обещают сообщать об ошибках процесса, если это вообще возможно (если плеер вообще получает какую-то информацию от внешней среды, с которой взаимодействует в процессе асинхронной операции). Приведите конкретный пример, посмотрим.

Mirror13 29.04.2012 22:04

Я не совсем это имел в виду. Ясное дело, что try/catch не работает с асинхронными вызовами. Вопрос в том, есть ли способы сделать механизм для обработки ошибок при асинхронных вызовах, который был бы так же удобен, как исключения при синхронных.

Как пример можно привести обертку для запросов на сервер. Допустим, там есть метод:
Код AS3:

public function getData(resource:String, onSuccess:Function, onError:Function):void
{
    _applyRequest(resource, URLRequestMethod.GET, onSuccess, onError);
}

Внутри метода _applyRequest есть такой код:
Код AS3:

loader.addEventListener(IOErrorEvent.IO_ERROR, onLoadError);
loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onLoadError);

И, соответственно:
Код AS3:

function onLoadError(e:ErrorEvent):void {
    e.target.removeEventListener(e.type, arguments.callee);
    if (onError !== null)
        onError(e);
    else
        throw 'Network error';
}

Вот если бы можно было избавиться от протягивания коллбэка onError, а как-то через весь стек передать сигнал. В синхронном случае это исключение. В случае экранных объектов можно использовать dispatchEvent. А можно ли что-нибудь придумать в этом случае?

Wolsh 29.04.2012 23:03

Цитата:

Вопрос в том, есть ли способы сделать механизм для обработки ошибок при асинхронных вызовах, который был бы так же удобен, как исключения при синхронных.
В смысле предвидел ошибки до их появления?
Как может асинхронный быть таким же, как синхронный? Помните картинку популярную с кубиками, на которых написаны буквы "А","П","Ж" и "О", и "пока не соберешь слово СЧАСТЬЕ, домой не пойдешь"?
Цитата:

Вот если бы можно было избавиться от протягивания коллбэка onError, а как-то через весь стек передать сигнал.
Кому передать? Уже нет никакого стека. Он кончился, остался в прошлом. Избавиться от протягивания — пожалуйста, просто подпишитесь на события. Работайте с Объектом, а не с функцией. AS3 это ООП-язык. Вы просите Объект загрузить данные. Объект участливо предоставляет Вам события. Зачем создавать свою систему поставок через единый коннектор-метод, непонятно. Вы никак не обработаете ошибку до ее появления. Вам придется резать код на методы-обработчики, как бы ни хотелось писать функцию-простыню в 1000 строк. Асинхронная ошибка это Событие по самой своей сути. То, как поступают с ней в языке — естественное природное поведение, и нарушить законы времени не удастся. Код не будет сам стоять и ждать, что ответит getData. Для этого надо поставить закрывающую скобку и написать новый блок, который запустится, когда хозяин getData отрапортует об исходе операции.

Mirror13 29.04.2012 23:13

Ясно.

Я так понимаю, что для использования событий нужно, чтобы класс наследовался от EventDispatcher'а. В этом случае можно будет делать примерно так:
Код AS3:

serverDataInstance.addEventListener(ServerData.ERROR_EVENT, onError);

И, соответственно:
Код AS3:

function onLoadError(e:ErrorEvent):void {
    e.target.removeEventListener(e.type, arguments.callee);
    dispatchEvent(new Event(ERROR_EVENT));
}

Но всплыть на несколько уровней вверх это событие не сможет, и перехватить его можно будет только на том уровне, где был создан serverDataInstance, я правильно понимаю?

Wolsh 29.04.2012 23:45

Да. Создаем объект и перед вызовом сомнительного метода подписываемся на событие об ошибке.
А зачем выше? Чтобы обрабатывать все в Едином Центре Ошибок в Мейне? То есть Мейну надо будет знать детали реализации своих неуравновешенных детишек?)) Честно сказать, тут я не советчик — никогда не пытался строить архитектуру таким образом. Мне кажется, что с ошибкой в результате выполнения метода должен разбираться тот, кто этот метод вызвал. Но если не так, то придется на этот раз ему отсылать событие наверх, дескать "шеф, усё пропало!" Знаю, знаю. Опять протягивание, опять многоступенчатая передача. Но на деле мне кажется это не так страшно, как кажется))))) Я бы даже сказал, что здесь больше гибкости и осмысленности, но нет, у меня недостаточно опыта в построении систем с синхронными ошибками, чтобы сравнивать.
Цитата:

нужно, чтобы класс наследовался от EventDispatcher'а.
Есть еще композиция. Но обычно да, если хочется кастомные события то проще наследоваться (если действительно кастомные, то есть собственный класс событий, а не строковый тип).
Цитата:

Но всплыть на несколько уровней вверх это событие не сможет
Вроде есть самопальные реализации всплытия для недисплейных цепочек, поищите, я сам не интересовался настолько подробно.

Mirror13 30.04.2012 00:26

Спасибо за информацию )
Цитата:

А зачем выше? Чтобы обрабатывать все в Едином Центре Ошибок в Мейне?
Вполне может пригодиться для фатальных ошибок, при которых дальше работать не имеет смысла. К примеру, приложение требует постоянной связи с сервером, а ее нет - нужно уведомить пользователя, что все пропало, и остановить работу.

Но, видимо, не судьба ) Вряд ли самостоятельно реализовывать всплытие по всем уровням лучше, чем вызывать нужные коллбэки или передавать по всем уровням событие.

Цитата:

Есть еще композиция. Но обычно да, если хочется кастомные события то проще наследоваться (если действительно кастомные, то есть собственный класс событий, а не строковый тип).
Я не большой знаток этого паттерна, но я так понимаю, он не совсем подойдет для общего случая.

Композиция - если я правильно понимаю, это иерархия объектов с одинаковым интерфейсом, в которых как раз реализована передача сообщений от нижнего уровне наверх. Как DOM в HTML или дерево экранных объектов во Flash'е. А мне было интересно, что делать в общем случае.

Выходит, в месте непосредственного возникновения ошибки лучше использовать события, а если нужно передать наверх - по обстоятельствам.

ChuwY 30.04.2012 00:38

Вы путаете с паттерном "компоновщик".
Композиция это отношение "включает в себя", противопостовляющееся наследованию, выражающему "является".

Добавлено через 1 минуту
Кстати, реализовать свое всплытие не сложно и вполне себе кошерно пользоваться этим.
(реализовывал, но пользоваться не приходилось, если честно. просто случаев не представлялось, хотя есть идеи)


Часовой пояс GMT +4, время: 06:36.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.