處理應用程式中的同步錯誤

Flash Player 9 以及更新的版本,Adobe AIR 1.0 以及更新的版本

最常用的錯誤處理程序是同步錯誤處理邏輯,也就是將陳述式插入程式碼,在應用程式執行時捕捉同步錯誤。這種類型的錯誤處理方式可以讓您的應用程式在功能失敗時,注意到執行階段錯誤並加以復原。捕捉同步錯誤的邏輯包括 try..catch..finally 陳述式,此陳述式基本上會重複嘗試執行作業、捕捉來自 Flash 執行階段的錯誤回應,最後再執行部分其它作業以處理失敗的作業。

使用 try..catch..finally 陳述式

當您在處理同步執行階段錯誤時,請使用 try..catch..finally 陳述式來捕捉錯誤。一旦發生執行階段錯誤,Flash Player 或 Adobe AIR 就會擲回例外。也就是說,Flash 執行階段會暫停正常的執行作業,並建立類型為 Error 的特殊物件。接著該 Error 物件會擲向第一個可用的 catch 區塊。

try 陳述式包含可能會造成錯誤的陳述式。使用 catch 陳述式時,請務必搭配 try 陳述式。如果在 try 陳述式區塊的其中一個陳述式內偵測到錯誤,就會執行附加到 try 陳述式的 catch 陳述式。

不管 try 區塊中是否發生錯誤,都會執行 finally 陳述式所包含的陳述式。如果沒有錯誤,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); 
}

ActionScript API 中的幾個方法和屬性如果在執行時遇到錯誤,則會擲回執行階段錯誤。例如,當 Sound 類別中的 close() 方法無法關閉聲音串流時,便會擲回 IOError,如下列程式碼所示:

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

當您更熟悉適用於 Adobe Flash Platform 的 ActionScript 3.0 參考之後,會注意到哪些方法會擲回例外,這些都會在每個方法的說明中詳述。

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 陳述式是依序排列的,因此最明確的資料類型會排在第一。如果 Number 資料類型的 catch 陳述式排在第一,則 uint 資料類型的 catch 陳述式和 int 資料類型的 catch 陳述式都不會執行。

備註: 在 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 區塊,此區塊會在巢狀 catch 區塊無法處理錯誤時,重新擲回自訂的 ApplicationError:

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 區塊。