lunes, 10 de diciembre de 2007

Llamadas Asincrónicas

Tecnologías como Flex, Ajax, .NET entre otras, hacen uso de lo que se conoce como comunicación asincrónica. Esto es: llamadas a un cierto servicio en las cuales no sabemos cuando se recibirá la respuesta. Hay mucho factores que pueden modificar el tiempo de respuesta de un servicio, como puede ser la carga en el server, bandwidth del cliente, entre otros...
En comunicaciones sincronizadas, la aplicación no continuará trabajando hasta que reciba una respuesta a la petición hecha, en una aplicación asincrónica no.
Pensando en este ambiente, planteo la siguiente situación que se puede presentar en cualquier tecnología asincrónima:

Se tienen dos botones, que se conectan a un mismo servicio (archivo XML, un script PHP, ASP, JSP, un webservice o lo que sea) pero que hacen distintas funciones, se presiona uno primero y medio segundo después el segundo... En la forma en que se programa asincrónimamente, no sabemos cual respuesta va a llegar primero, puede ser la del segundo boton y después la respuesta del primero. Si nos ponemos a programar y pensar "sincronizadamente", esperaríamos la primer respuesta y luego la segunda y esto puede ocasionar problemas en nuestras aplicaciones ya que si el orden es distinto la forma en que se manejará la respuesta variará el procesamiento de la respuesta recibida y por lo tanto el funcionamiento normal de la aplicación.

Solución en Flex

El AsyncToken es una clase usada para manejar llamadas asincronicas... Es aplicable con lo que se conoce como el ACT Pattern o Asyncronous Completition Token. Este patrón se encarga de procesar la acción indicada a la respuesta recibida a una llamada asincrónima. Esto quiere decir que la llamada realizada por el boton 2, no procesara la acción a la respuesta del llamado del botón 1 aunque llegase primero... sino solamente la que esta relacionada con su llamada.

Las funciones principales del AsyncToken son agregar información que puede ser util para identificar la llamada... y permitir definir quien se encargara de procesar los resultados(y sus fallas en caso que hayan).

Como ejemplo para el primer caso que mencione antes (identificacion de quien hizo una llamada), al trabajar asincronimamente no sabemos cuando iremos a recibir el resultado, en el ejemplo anterior de los botones que se conectan a un mismo remote object pero hacen distintas funciones, se presiona el primero e inmediatamente el segundo.. como va a saber el Result Handler cual de los dos llamados fue invocado? El ASyncToken nos permite agregar cierta informacion que permitira marcar cada llamada y asi se sabra como procesar cada
informacion.... Este token sera agregado al llamado, así que cuando se reciba información el token va a ir pegado con el evento resultado.
Por ejemplo (muy basico) utilizando una "bandera" en el token, que se llamará marker:

//Ejecutado cuando se presiona Boton 1.
private function llamada1():void{
var token:AsyncToken = remote_object.agregarUsuario(instancia_usuario);
token.marker= "agregarUsuario";
}

//Ejecutado cuando se presiona Boton 2.
private function llamada2():void{
var token:AsyncToken = remote_object.modificarUsuario(instancia_usuario);
token.marker= "modificarUsuario";
}

private function resultHandler(event:ResultEvent):void{
var token:Object = event.token;//se carga desde el evento, el token que se instanció en cada función
if(token.marker == "agregarUsuario"){

//codigo para manipular resultado cuando se agrega usuario

}else if(token.marker == "modificarUsuario"){

//Codigo para manipular resultado de modificar usuario...

}
}

Ya en Cairngorm especificamente, en el delegate se utiliza esta funcionalidad, ya que permite asignar quien se encargara de procesar los resultados de una llamada a servicio externo. Generalmente en la comunidad de flex, se le encarga esa responsabilidad a los comandos, por eso los comandos con llamados a datos externos (remote objects, web services o http services) generalmente implementan la interfaz IResponder, que expone los servicios: result(en caso de resultado satisfactorio) y fault (en caso de error). Lo que permite concretamente el asynctoken en este caso, es asignar a otra clase el manejo de los resultados que se vayan a recibir, ej desde un delegate:

var call:AsyncToken = service.agregarUsuario(instancia_usuario);
call.addResponder(responder);

En este caso, quien manejara los resultados del metodo agregar usuario, no sera el delegate, sino el objeto Responder, que será un objeto de un tipo de Clase que implemente IResponder (como mencione antes) y que generalmente es el command, aunque se puede hacer aun en otra clase, para "favorecer la composicion sobre la herencia", pero eso es tema de otro topic...

Así de sencillo, lo bueno es que por la arquitectura de servicios que tiene el Flex, esta misma solución es aplicable a Web Services, HTTP Services y Remote Objects.
Saludos

No hay comentarios: