É tão bom quando você tem alguns minutos livres durante a semana para escrever alguma coisa no blog, que ultimamente tem sido tão deixado de lado!
Uma das grandes novidades do Flash Player 10.1 é a possibilidade de capturar todos os erros gerados pela sua aplicação RIA.
Comumente, desenvolvedores e inclusive nós, tinhamos o hábito de capturar os erros apenas comuns em uma aplicação, por exemplo: IOError, Load Errors, Event Erros, Converter Errors, porém querendo ou não acaba escapolindo do nosso controle uns errinhos como 1009,1056,2048 etc. Esses erros é de tirar o fôlego quando se trata de experiência do usuário, e principalmente quando se tem vários deles.
Infelizmente, isso já era para estar pronto desde a versão 9. Como não tinha, faziamos isso como comentei acima. O que, torna uma tarefa repetitiva e acaba virando um saco fazer sempre aquilo, embora você tente ao máximo re-utilizar seu código.
Contudo, para a grande saúde mental de desenvolvedores, a Adobe decidiu criar esse tipo de captura, dando ao desenvolvedor a oportunidade de verificar quais erros estavam ou estão sendo gerados tanto em backgrounds não mostrados no Stacker ou mostrados.
Nem tudo é um mar de rosas, esse tipo de captura de evento só funciona se seu navegador estiver com o Flash Player do tipo debug, inclusive acaba ficando disponivel apenas para usuarios desenvolvedores, impossibilitando assim você de logar automaticamente um erro e captura-lo e adiciona-lo a uma base de análise, que é comumente feito em sistemas enterprise.
Como era feito a captura de erros até então no Flash Player 9 e 10:
Geralmente como nossos requisitos sempre são simples, nada tão complexo, preferimos usar não a classe padrão de Log de erro do SDK do Flex, por que é além do que agente precisa, e como também existem outras ferramentas e frameworks no mercado para log de erros.
A classe LogManager ela adiciona os erros a um arrayCollection:
package com.igorcosta.debug
{
import mx.collections.ArrayCollection;
public class LogManager
{
[Bindable]private static var _arrError:ArrayCollection = new ArrayCollection();
public static function get errors():ArrayCollection
{
return _arrError;
}
public function LogManager()
{
}
public static function addError(error:LogError):void
{
_arrError.addItem(error);
}
}
}
E a classe que agente costuma chamar de LogError, nada mais é que um VO/DTO, etc:
package com.igorcosta.debug
{
public class LogError
{
public function LogError()
{
}
public var stack:String;
public var name:String;
public var ID:String;
public var message:String;
}
}
Ai para usarmos em um simples teste de erro, veja o aplicativo que fizemos para esse post. Acho que vai ajudar vocês a melhor enxergar como é penoso o trabalho de capturar os eventos.
< ?xml version="1.0" encoding="utf-8"?>
<application xmlns="http://www.adobe.com/2006/mxml" layout="vertical">
<script>
< ![CDATA[
import mx.controls.Label;
import com.igorcosta.debug.LogManager;
import mx.utils.ObjectUtil;
import com.igorcosta.debug.LogError;
public var err:LogError;
public function provocarErro(tipo:uint):void
{
switch(tipo){
case 1:
try{
throw new IOError("I/O Error, de leitura ou escrita");
}catch(erro:IOError){
err = new LogError();
err.stack = erro.getStackTrace();
err.message = erro.message;
err.ID = String(erro.errorID);
err.name = erro.name;
LogManager.addError(err);
}
break;
case 2:
try{
var temp:Label;
temp.text = 'test';
}catch(erro:Error){
err = new LogError();
err.stack = erro.getStackTrace();
err.message = erro.message;
err.ID = String(erro.errorID);
err.name = erro.name;
LogManager.addError(err);
}
break;
case 3:
try{
stackTest();
}catch(erro:Error){
err = new LogError();
err.stack = erro.getStackTrace();
err.message = erro.message;
err.ID = String(erro.errorID);
err.name = erro.name;
LogManager.addError(err);
}
}
}
private function stackTest():void
{
stackTest();//loop de funcao da um erro de StackOverflow
}
]]>
</script>
<hbox width="100%">
<button label="Provocar erro 1009" click="provocarErro(2)"/>
<button label="Provocar erro IO" click=" provocarErro(1)"/>
<button label="Provocar erro Stack Overflow" click=" provocarErro(3)"/>
</hbox>
<datagrid dataProvider="{LogManager.errors}" x="103" y="160" width="743" height="308">
<columns>
<datagridcolumn headerText="Nome do Erro" dataField="stack"/>
<datagridcolumn headerText="Nome do Erro" dataField="name"/>
<datagridcolumn headerText="Mensagem de erro" dataField="message"/>
<datagridcolumn headerText="ID do erro" dataField="ID"/>
</columns>
</datagrid>
</application>
Capturando erros gerais ou “Global Error handler” no Flash Player 10.1 e AIR 2.0:
Agora usando o mesmo aplicativo, podemos capturar qualquer tipo de erro gerado pelo Flash Player, ou mau uso do código. Um detalhe é que o novo recurso do Flash Player o Uncaught Error e Uncaught Error Event, são passÃveis de receber qualquer erro ocorrido no swf compilado. Veja o exemplo abaixo:
< ?xml version="1.0" encoding="utf-8"?>
<mx :Application xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="completou()" layout="vertical">
</mx><mx :Script>
< ![CDATA[
import mx.controls.Label;
import com.igorcosta.debug.LogError;
import com.igorcosta.debug.LogManager;
private function completou():void
{
loaderInfo.uncaughtErrorEvents.addEventListener(UncaughtErrorEvent.UNCAUGHT_ERROR, capturarErros);
}
private function capturarErros(e:UncaughtErrorEvent):void
{
if(e.error is Error){
Error(e.error).getStackTrace();
LogManager.addError(e.error as Error);
}
if(e.error is ErrorEvent){
LogManager.addErrorEvent(e.error as ErrorEvent);
}
}
private function identifica(e:MouseEvent):void
{
var minhaVar:Label;
try
{
minhaVar.text = " Ola Mundo" ;
}
catch (e:Error)
{
// capturou o erro
minhaVar as Boolean;
trace(minhaVar.text);
}
}
]]>
</mx>
<mx :HBox width="100%" >
<mx :Button label="Causar erro de acesso indefinido" click="identifica(event);"/>
</mx>
<mx :DataGrid width="100%" dataProvider="{LogManager.errors}" x="29" y="182">
</mx><mx :columns>
<mx :DataGridColumn headerText="ID do Erro" dataField="errorID"/>
<mx :DataGridColumn headerText="Nome do erro" dataField="name"/>
<mx :DataGridColumn headerText="Mensagem de erro" dataField="message"/>
</mx>
Lembrando que para você usar em seu projeto esse recurso do UncaughtError e UncaughtErrorEvent, você precisa ter o playerglobal.swc do Flash player 10.1, tanto para o Flash Player quanto para o AIR 2.0.
Os códigos fontes de ambos os aplicativos vocês podem baixar diretamente aqui.
Comentários feitos