Gestione degli errori sincroni delle applicazioni

Flash Player 9 e versioni successive, Adobe AIR 1.0 e versioni successive

La modalità di gestione degli errori più comune è costituita dalla logica di gestione degli errori sincroni, che consiste nell'inserire istruzioni nel codice per catturare gli errori sincroni quando un'applicazione è in esecuzione. Questo tipo di approccio permette all'applicazione di rilevare e risolvere i problemi in fase di runtime quando le funzioni non vengono eseguite. La logica di cattura di un errore asincrono comprende istruzioni try..catch..finally, che tentano di eseguire un'operazione, catturano le eventuali risposte di errore dal runtime Flash e infine eseguono altre operazioni per gestire l'operazione non riuscita.

Utilizzo delle istruzioni try..catch..finally

Quando si lavora con errori in fase di runtime, utilizzate le istruzioni try..catch..finally per catturare gli errori. Quando si verifica un errore runtime, il runtime Flash genera un'eccezione, ovvero sospende la normale esecuzione del codice e crea un oggetto speciale del tipo Error. L'oggetto Error viene quindi rilevato dal primo blocco catch disponibile.

L'istruzione try racchiude istruzioni che hanno il potenziale di creare errori e viene sempre combinata a un'istruzione catch. Se viene rilevato un errore in una delle istruzioni del blocco try, le istruzioni catch collegate a quella particolare istruzione try vengono eseguite.

L'istruzione finally racchiude istruzioni eseguite indipendentemente dalla presenza di errori nel blocco try. In assenza di errori, le istruzioni del blocco finally vengono eseguite al termine delle istruzioni del blocco try. In presenza di un errore, viene innanzitutto eseguita l'istruzione catch appropriata seguita dalle istruzioni del blocco finally.

Il codice seguente dimostra la sintassi da impiegare per le istruzioni 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. 
}

Ogni istruzione catch identifica un tipo di eccezione specifica da gestire. L'istruzione catch può specificare solo sottoclassi della classe Error. Le istruzioni catch vengono verificate in sequenza, ma viene eseguita solo la prima istruzione catch che coincide al tipo di errore generato. In altre parole, se controllate per prima la classe Error di livello più alto e quindi una sottoclasse di questa classe, solo la classe Error di livello più alto evidenzia una corrispondenza. Il codice seguente illustra questo punto:

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

Il codice precedente visualizza il seguente output:

<Error> I am an ArgumentError

Per rilevare correttamente l'errore ArgumentError, verificate che i tipi specifici di errore siano elencati per primi seguiti dai tipi di errore più generici, come illustrato nel codice seguente:

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

Vari metodi e proprietà dell'API di ActionScript generano errori in fase di runtime se rilevano errori durante la loro esecuzione. Ad esempio, il metodo close() della classe Sound genera un errore IOError se il metodo non riesce a chiudere lo streaming audio, come illustrato nel codice seguente:

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

Man mano che acquisite dimestichezza con la Guida di riferimento di Adobe ActionScript 3.0 per la piattaforma Adobe Flash, vi renderete conto dei metodi che generano eccezioni, come illustrato nella descrizione dei singoli metodi.

L'istruzione throw

I runtime Flash generano eccezioni quando incontrano errori nell'applicazione in esecuzione. Inoltre, lo sviluppatore può espressamente generare delle eccezioni usando l'istruzione throw. Per generare esplicitamente delle eccezioni, Adobe consiglia di generare istanze della classe Error o di sue sottoclassi. Il codice seguente illustra il funzionamento di un'istruzione throw che genera un'istanza della classe Error, MyErr, quindi chiama la funzione myFunction() per rispondere all'errore generato:

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

Notate che la sequenza delle istruzioni catch parte da quella contenente i dati più specifici. Se l'istruzione catch per il tipo di dati Number è elencata per prima, né l'istruzione catch per il tipo di dati uint né l'istruzione catch per il tipo di dati int verranno mai eseguite.

Nota: nel linguaggio di programmazione Java, ogni funzione che ha la facoltà di generare un'eccezione deve dichiararlo e indicare le classi di eccezione che possono essere generate in un'apposita clausola throws collegata alla descrizione della funzione. ActionScript non pone questo vincolo, perciò non è necessario dichiarare le eccezioni che una funzione può generare.

Visualizzazione di un messaggio di errore semplice

Uno dei principali vantaggi che offre il nuovo modello di generazione di eccezioni ed errori è che permette di comunicare agli utenti quando e perché un'azione non è andata a buon fine. Lo sviluppatore si deve occupare di scrivere il codice necessario per visualizzare il messaggio e presentare le opzioni per l'utente.

Il codice seguente mostra una semplice istruzione try..catch per visualizzare l'errore in un campo di testo:

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

Poiché si avvale di una gamma più ampia di classi di errore e di errori del compilatore incorporati, ActionScript 3.0 consente di visualizzare maggiori dettagli sulle operazioni non eseguite rispetto alle versioni precedenti del programma. Queste informazioni consentono di creare applicazioni più stabili con procedure di gestione degli errori più efficaci.

Generazione ripetuta di errori

Durante la creazione delle applicazioni, si verifica spesso la necessità di ripetere la generazione di un errore che non è stato possibile gestire correttamente. Ad esempio, il codice seguente mostra un blocco try..catch nidificato, che genera un errore ApplicationError personalizzato se il blocco catch nidificato non è in grado di gestire l'errore:

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

L'output generato dallo snippet di codice precedente sarebbe il seguente:

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

Il blocco try nidificato genera un errore ApplicationError personalizzato catturato dal blocco catch successivo. Questo blocco catch nidificato può provare a gestire l'errore ma, se l'esito è negativo, genera l'oggetto ApplicationError diretto al blocco try..catch.