Обработка синхронных ошибок в приложении

Flash Player 9 и более поздних версий, Adobe AIR 1.0 и более поздних версий

Наиболее распространенной системой обработки ошибок является синхронная логика. При этом в код вставляются инструкции, которые перехватывают синхронные ошибки во время выполнения программы. Этот тип обработки ошибок позволяет приложению обнаруживать и устранять ошибки выполнения в случае функциональных сбоев. Логика перехвата синхронных ошибок включает инструкции try..catch..finally , которые проверяют (try) операцию, перехватывают (catch) любые ответы на ошибку от среды выполнения Flash и в заключение (finally) выполняют какую-либо другую операцию, чтобы устранить сбой программы.

Использование инструкций try..catch..finally

При работе с синхронными ошибками выполнения для их перехвата используются инструкции try..catch..finally . Когда возникает ошибка выполнения, среда выполнения Flash генерирует исключение. Это означает, что нормальное выполнение программы приостанавливается, и создается специальный объект типа Error. Затем объект Error отправляется в первый доступный блок catch .

Инструкция try закрывает группу инструкций, которые потенциально могут создавать ошибки. Инструкция catch всегда используется с инструкцией try . Если обнаруживается ошибка в одной из инструкций блока try , начинается выполнение инструкций catch , которые прикреплены к данной инструкции try .

Инструкция finally закрывает инструкции, которые будут выполняться при возникновении ошибки в блоке try или нет. Если ошибки нет, инструкции внутри блока finally выполняются после завершения выполнения инструкций блока try . Если ошибка есть, сначала выполняется соответствующая инструкция catch , затем — инструкции блока finally .

Следующий код демонстрирует синтаксис для использования инструкций try..catch..finally :

try 
{ 
    // some code that could throw an error 
} 
catch (err:Error) 
{ 
    // code to react to the error 
} 
finally 
{ 
    // Code that runs whether an error was thrown. This code can clean 
    // up after the error, or take steps to keep the application running. 
}

Каждая инструкция catch идентифицирует специфический класс того исключения, которое он обрабатывает. Инструкция catch может задавать только те подклассы ошибок, которые принадлежат к классу Error. Каждая инструкция catch проверяется по порядку. Выполняется только первая инструкция catch , которая соответствует типу генерируемой ошибки. Другими словами, если проверяется сначала класс Error высшего уровня, а затем подкласс класса Error, тогда выбран будет только класс Error высшего уровня. Эту систему иллюстрирует следующий код:

try 
{ 
    throw new ArgumentError("I am an ArgumentError"); 
} 
catch (error:Error) 
{ 
    trace("<Error> " + error.message); 
} 
catch (error:ArgumentError) 
{ 
    trace("<ArgumentError> " + error.message); 
}

Выше приведенный код отображает следующий вывод:

<Error> I am an ArgumentError

Чтобы корректно перехватить ошибку ArgumentError, наиболее специфические типы ошибок должны быть перечислены в начале, а наиболее общие — в конце, как показано в следующем примере:

try 
{ 
    throw new ArgumentError("I am an ArgumentError"); 
} 
catch (error:ArgumentError) 
{ 
    trace("<ArgumentError> " + error.message); 
} 
catch (error:Error) 
{ 
    trace("<Error> " + error.message); 
}

Некоторые методы и свойства в API-интерфейсе ActionScript генерируют ошибки выполнения, если они сталкиваются с ошибками во время работы. Например, метод close() в классе Sound генерирует ошибку IOError, если он (метод) не в состоянии закрыть аудиопоток, как демонстрируется в следующем коде:

var mySound:Sound = new Sound(); 
try 
{ 
    mySound.close(); 
} 
catch (error:IOError) 
{ 
    // Error #2029: This URLStream object does not have an open stream. 
}

Изучив cправочник ActionScript® 3.0 для платформы Adobe® Flash® Platform , вы обратите внимание на то, какие методы генерируют исключения. Это детально описано для каждого метода.

Инструкция throw

Среды выполнения Flash генерируют исключения, когда сталкиваются с ошибками в процессе работы вашего приложения. Кроме того, программист может генерировать определенные исключения самостоятельно, используя инструкцию throw . При эксплицитной генерации ошибок компания Adobe рекомендует генерировать экземпляры класса Error или его подклассов. Ниже приведен код, в котором инструкция throw генерирует экземпляр класса Error MyErr , а затем вызывает функцию myFunction() для ответа после генерации ошибки:

var MyError:Error = new Error("Encountered an error with the numUsers value", 99); 
var numUsers:uint = 0; 
try 
{ 
    if (numUsers == 0) 
    { 
        trace("numUsers equals 0"); 
    } 
} 
catch (error:uint) 
{ 
    throw MyError; // Catch unsigned integer errors. 
} 
catch (error:int) 
{ 
    throw MyError; // Catch integer errors. 
} 
catch (error:Number) 
{ 
    throw MyError; // Catch number errors. 
} 
catch (error:*) 
{ 
    throw MyError; // Catch any other error. 
} 
finally  
{ 
    myFunction(); // Perform any necessary cleanup here. 
}

Обратите внимание, что инструкции catch упорядочены таким образом, что типы с наиболее специфичными данными следуют первыми. Если инструкция catch с типом данных Number следует первой, тогда ни инструкция catch с типом данных uint, ни инструкция catch с типом данных int уже не будут выполняться.

Примечание. В языке программирования Java каждая функция, генерирующая исключение, должна объявить этот факт, перечислив доступные для генерации классы в предложении throws , прикрепленном к объявлению функции. В ActionScript не требуется объявлять исключения, которые может генерировать функция.

Отображение простых сообщений об ошибках

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

В следующем коде показано простая инструкция try..catch для отображения сведений об ошибке в текстовом поле:

package 
{ 
    import flash.display.Sprite; 
    import flash.text.TextField; 
     
    public class SimpleError extends Sprite 
    { 
        public var employee:XML =  
            <EmpCode> 
                <costCenter>1234</costCenter> 
                <costCenter>1-234</costCenter> 
            </EmpCode>; 
 
        public function SimpleError() 
        { 
            try 
            { 
                if (employee.costCenter.length() != 1) 
                { 
                    throw new Error("Error, employee must have exactly one cost center assigned."); 
                } 
            }  
            catch (error:Error) 
            { 
                var errorMessage:TextField = new TextField(); 
                errorMessage.autoSize = TextFieldAutoSize.LEFT; 
                errorMessage.textColor = 0xFF0000; 
                errorMessage.text = error.message; 
                addChild(errorMessage); 
            } 
        } 
    } 
}

Используя расширенный набор классов ошибок и встроенных ошибок компиляции, ActionScript 3.0 предоставляет больше информации о сбоях по сравнению с предыдущими версиями ActionScript. Эта информация позволяет создавать более стабильные приложения с улучшенной системой обработки ошибок.

Повторная генерация ошибок

При создании приложений существуют различные ситуации, в которых требуется повторно генерировать ошибку, если ее не удалось должным образом обработать. Например, в следующем коде показан вложенный блок try..catch , который повторно генерирует пользовательскую ошибку ApplicationError, если вложенный блок catch не может обработать данную ошибку:

try 
{ 
    try 
    { 
        trace("<< try >>"); 
        throw new ApplicationError("some error which will be rethrown"); 
    } 
    catch (error:ApplicationError) 
    { 
        trace("<< catch >> " + error); 
        trace("<< throw >>"); 
        throw error; 
    } 
    catch (error:Error) 
    { 
        trace("<< Error >> " + error); 
    } 
} 
catch (error:ApplicationError) 
{ 
    trace("<< catch >> " + error); 
}

Результатом предыдущего фрагмента будет следующее:

<< try >> 
<< catch >> ApplicationError: some error which will be rethrown 
<< throw >> 
<< catch >> ApplicationError: some error which will be rethrown

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