domingo, 6 de junho de 2010

Controlando o processamento assíncrono

Blz?!

Depois de mais de um mês sem postar nada desta vez vou mostrar uma maneira simples, porém muito eficaz de controlar o processamento assíncrono. Você já deve ter ficado com

muita raiva quando por exemplo existem dois métodos, o primeiro faz uma consulta a base de dados e o segundo toda uma decisão com base nas informações do primeiro método, mas a consulta demora mais que devia e o segundo método é executado como ainda não houve retorno do primeiro método de duas uma, blz não vai acontecer nada (oque já não é nada bom) ou vai "explodir" um erro na cara do usuário (ainda pior). Então para controlar isso vamos "amarrar" a execução dos métodos passando-os como parâmetro, nesse exemplo vão ver dois botões "Sem controle" e "Com controle".
Sem controle é a chamada dos método da maneira tradicional onde você colocaria os métodos um logo abaixo do outro conforme a ordem de execução, já "Com controle" os métodos são passados na assinatura dos métodos (confuso? vai ficar mais tranquilo ao ver o código) assim quem foi passado somente será executado ao final do primeiro método.

import mx.collections.ArrayCollection;
import mx.controls.Alert;
import mx.managers.CursorManager;

[Bindable]
private var _uDado: ArrayCollection = new ArrayCollection();

/* Na assinatura do método há um parâmetro do tipo Function que
pode ou não ser informado dependendo da necessidade */
private function metodoUm(OnRetorna: Function = null): void {
  var
    _rResult: Number,
    I: int;
  
  CursorManager.setBusyCursor();
  
  // Um laço de repetição para simular uma operação "demorada"
  for (I = 0; I <= 99999; I++) {
    _rResult = (I * 90 + 88 / Math.PI + 9999 / .56 * 903.09); 
    _uDado.addItem(_rResult);
  }
  
  /* Se for informado algum método ao "chamar" o métodoUm
  é agora que ele será "chamado" */
  if (OnRetorna != null)
    OnRetorna();  
}

private function metodoDois(): void {
  // Bloco try para capturar o erro
  try {
    mResultado.text += '\n' + _uDado[99999];
  }
  catch (erro: Error) {
    mResultado.text += '\n' + erro.message;
  }
  
  // Remove o busy
  CursorManager.removeAllCursors();
}

private function clickBtnSemControle(): void {
  /* Aqui a o modo "tradicional" onde os método são colocados
  na ordem de execução */
  metodoUm();
  metodoDois();
}

private function clickBtnComControle(): void {
  // Aqui colocando um pouco mais de ordem nas coisas
  metodoUm(metodoDois);
} 


Ps.: Nos testes o método "Sem controle" deu erro duas a cada dez execuções,
portanto não se engane se ao executar o exemplo parecer que as duas maneiras
sempre terão o mesmo resultado.



Bons estudos e bom trabalho a todos.

Abraços

2 comentários:

Uma outra abordagem seria o uso de eventos (custom event):

Ao terminar a operação do métodoUm, vc dispara um evento onde um listener irá tratar o evento e executar o métodoDois.

Dessa forma, vc não 'acopla' os métodos envolvidos (tipo, o metodoUm somente dispara o evento - nao interessa quem irá 'ouvir' - e o metodoDois só é executado qnd o evento for disparado).

[]s

Antes de mais nada é uma honra o mestre Mario Junior está "passeando" pelo blog =D

Concordo, mas eu particularmente evito fazer listener´s, desta maneira que eu demonstrei é muito útil quando você tem duas telas identicas abertas e o resultado vem de uma outra classe, se você disparar um evento as duas estão prontas para "ouvir" este evento, isso irá refletir nas duas independente de da tela que chamou o método que disparou o evento já "acoplando" com function o retorno só volta (retorno volta ficou estranho..rs) para quem efetivamente fez a chamada.

[]´s

Postar um comentário

Twitter Delicious Facebook Digg Stumbleupon Favorites More