Obsługa błędów synchronicznych w aplikacji

Flash Player 9 i nowsze wersje, Adobe AIR 1.0 i nowsze wersje

Najczęściej używaną obsługą błędów jest synchroniczna logika obsługi błędów, gdzie instrukcje wstawiane są do kodu w celu przechwycenia błędów synchronicznych w czasie działania aplikacji. Ten typ obsługi błędów pozwala aplikacji zauważyć niepowodzenie funkcji i powrócić z błędów czasu wykonywania do stanu normalnego. Logika do przechwytywania błędu synchronicznego obejmuje instrukcje try..catch..Instrukcje finally , które dosłownie próbują (try) wykonać operację, przechwytują ze środowiska wykonawczego Flash reakcję na błąd i na końcu wykonują inne operacje w celu obsługi operacji zakończonej niepowodzeniem.

Korzystanie z instrukcji try..catch..finally

Podczas pracy z synchronicznymi błędami czasu wykonania w celu przechwycenia błędów należy używać instrukcji try..catch..finally . W momencie wystąpienia błędu czasu wykonywania środowisko wykonawcze Flash generuje wyjątek, który oznacza zawieszenie normalnego wykonywania i utworzenie specjalnego obiektu typu Error. Obiekt Error jest następnie generowany w pierwszym dostępnym bloku catch .

Instrukcja try obejmuje instrukcje, które potencjalnie mogą tworzyć błędy. Instrukcji catch należy zawsze używać z instrukcją try . Jeśli błąd wykryty zostanie w jednej z instrukcji bloku try , wykonane zostaną instrukcje catch dołączone do tej instrukcji try .

Instrukcja finally obejmuje instrukcje, które zostaną wykonane bez względu na wystąpienie błędu w bloku try . W przypadku braku błędu instrukcje bloku finally zostaną wykonane po zakończeniu instrukcji bloku try . W przypadku błędu najpierw wykonana zostanie odpowiednia instrukcja catch , po której następują instrukcje bloku finally .

Poniższy kod przedstawia składnię dla instrukcji 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. 
}

Każda instrukcja catch identyfikuje konkretny typ wyjątku, który obsługuje. Instrukcja catch może określać tylko klasy błędu, które są podklasami klasy Error. Każda instrukcja catch sprawdzana jest w kolejności. Wykonana zostanie jedynie pierwsza instrukcja catch , która jest zgodna z wygenerowanym typem błędu. Innymi słowy: jeśli najpierw sprawdzona zostanie klasa Error wyższego poziomu, a następnie podklasa klasy Error, tylko klasa Error wyższego poziomu będzie klasą zgodną. Poniższy kod ilustruje tę sytuację:

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

Powyższy kod wyświetla na wyjściu następujący wiersz:

<Error> I am an ArgumentError

Aby poprawnie przechwycić ArgumentError, należy upewnić się, że na początku wyświetlane są najbardziej charakterystyczne typy błędów, a bardziej ogólne typy błędów wyświetlane są w dalszej kolejności tak, jak przedstawia to poniższy kod:

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

W momencie napotkania błędu podczas wykonywania kilka metod i właściwości interfejsu API ActionScript generuje błędy czasu wykonania. Na przykład metoda close() klasy Sound generuje błąd klasy IOError, jeśli metoda nie może zamknąć strumienia audio; przypadek został przedstawiony w poniższym kodzie:

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

Po bliższym zapoznaniu się ze Skorowidzem języka ActionScript 3.0 dla platformy Adobe Flash użytkownik dowie się, które metody generują wyjątki, ponieważ opis każdej metody zawiera odpowiednie informacje.

Instrukcja throw

Środowiska wykonawcze Flash generują wyjątki po napotkaniu błędów w uruchomionej aplikacji. Ponadto wyjątki można samodzielnie i jawnie generować za pomocą instrukcji throw . W czasie jawnego generowania błędów firma Adobe zaleca generowanie instancji klasy Error oraz jej podklas. W poniższym kodzie przedstawiona została instrukcja throw , która generuje instancję klasy Error ( MyErr ) oraz wywołuje na końcu funkcję myFunction() , aby zareagować na wygenerowany błąd:

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. 
}

Należy zauważyć, że instrukcje catch mają ustaloną kolejność, dlatego najbardziej konkretne typy danych zostały umieszczone w kodzie jako pierwsze. Jeśli jako pierwsza występuje instrukcja catch dla danych typu Number, wówczas nigdy nie zostanie wykonana instrukcja catch dla danych typu uint ani instrukcja catch dla danych typu int.

Uwaga: W języku programowania Java każda funkcja, która może wygenerować wyjątek musi zadeklarować ten fakt, umieszczając klasy wyjątków, jakie może wygenerować w klauzuli throws dołączonej do deklaracji funkcji. Język ActionScript nie wymaga od programisty deklarowania wyjątków, które mogą być generowane przez funkcję.

Wyświetlanie prostych komunikatów o błędach

Jedną z największych korzyści nowego modelu wyjątku i zdarzenia błędu jest to, że umożliwia programiście informowanie użytkowników o tym kiedy i dlaczego operacja się nie powiodła. Zadaniem programisty jest napisanie kodu do wyświetlania komunikatu i przedstawienie w odpowiedzi opcji wyboru.

Poniższy kod przedstawia prostą instrukcję try..catch do wyświetlania błędu w polu tekstowym:

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); 
            } 
        } 
    } 
}

Korzystając z szerszego zakresu klas błędów i wbudowanych błędów kompilatora, język ActionScript 3.0 oferuje więcej informacji o tym, dlaczego dany fragment kodu zakończył się niepowodzeniem niż poprzednie wersje języka ActionScript. Dzięki temu możliwe jest tworzenie stabilniejszych aplikacji z lepszą obsługą błędów.

Ponowne generowanie błędów

Istnieje kilka sytuacji podczas tworzenia aplikacji, w których może pojawić się potrzeba ponownego wygenerowania błędu, jeśli poprawna obsługa błędu okaże się niemożliwa. Na przykład: poniższy kod przedstawia zagnieżdżony blok try..catch , który ponownie generuje wspólny błąd klasy ApplicationError, jeśli zagnieżdżony blok catch nie jest w stanie obsłużyć błędu:

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); 
}

Na wyjściu poprzedniego kawałka kodu wyświetlone zostaną następujące wiersze:

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

Zagnieżdżony blok try generuje wspólny błąd klasy ApplicationError, który przechwytywany jest przez blok catch . Zagnieżdżony blok catch może spróbować obsłużyć błąd i jeśli próba zakończy się niepomyślnie, dla bloku try..catch wygenerowany zostanie obiekt ApplicationError.