¿La mejor manera de implementar eventos/devoluciones de llamadas asincrónicas 1:1 en ActionScript 3/Flex/AIR?
-
09-06-2019 - |
Pregunta
He estado utilizando el patrón de comando en mis proyectos Flex, con rutas de devolución de llamada asincrónicas requeridas entre:
- quien haya creado una instancia de un objeto de comando determinado y el objeto de comando,
- el objeto de comando y el objeto de "acceso a datos" (es decir,alguien que maneja las llamadas al procedimiento remoto a través de la red a los servidores) que llama el objeto de comando.
Cada una de estas dos rutas de devolución de llamada debe poder tener una relación uno a uno.Esto se debe al hecho de que puedo tener varias instancias de una determinada clase de comando ejecutando exactamente el mismo trabajo al mismo tiempo pero con parámetros ligeramente diferentes, y no quiero que sus devoluciones de llamada se mezclen.Por lo tanto, el uso de eventos, la forma predeterminada de manejar la asincronicidad en AS3, está prácticamente descartado ya que se basan inherentemente en relaciones de uno a muchos.
Actualmente he hecho esto usando referencias de la función de devolución de llamada con tipos específicos de firmas, pero me preguntaba ¿Si alguien conociera una forma mejor (o alternativa)?
Aquí hay un ejemplo para ilustrar mi método actual:
- Podría tener un objeto de vista que genere un
DeleteObjectCommand
instancia debido a alguna acción del usuario, pasando referencias a dos de sus propias funciones miembro privadas (una para el éxito, otra para el fracaso):digamos"deleteObjectSuccessHandler()"
y"deleteObjectFailureHandler()"
en este ejemplo) como referencias de función de devolución de llamada al constructor de la clase de comando. - Luego, el objeto de comando repetiría este patrón con su conexión al objeto de "acceso a datos".
- Cuando el RPC a través de la red se ha completado con éxito (o ha fallado), se llaman las funciones de devolución de llamada apropiadas, primero por el objeto de "acceso a datos" y luego por el objeto de comando, de modo que finalmente el objeto de vista que instancia la operación en la primera lugar es notificado al tener su
deleteObjectSuccessHandler()
odeleteObjectFailureHandler()
llamado.
Solución
Probaré una idea más:
Haga que su objeto de acceso a datos devuelva sus propios AsyncTokens (u otros objetos que encapsulan una llamada pendiente), en lugar del AsyncToken que proviene de la llamada RPC.Entonces, en DAO se vería así (este es un código muy incompleto):
public function deleteThing( id : String ) : DeferredResponse {
var deferredResponse : DeferredResponse = new DeferredResponse();
var asyncToken : AsyncToken = theRemoteObject.deleteThing(id);
var result : Function = function( o : Object ) : void {
deferredResponse.notifyResultListeners(o);
}
var fault : Function = function( o : Object ) : void {
deferredResponse.notifyFaultListeners(o);
}
asyncToken.addResponder(new ClosureResponder(result, fault));
return localAsyncToken;
}
El DeferredResponse
y ClosureResponder
Las clases no existen, por supuesto.En lugar de inventar el tuyo propio, podrías usar AsyncToken
en lugar de DeferredResponse
, pero la versión pública de AsyncToken
no parece tener ninguna forma de activar los respondedores, por lo que probablemente tendrías que subclasificarlo de todos modos. ClosureResponder
es solo una implementación de IResponder
que puede llamar a una función en caso de éxito o fracaso.
De todos modos, la forma en que el código anterior funciona es que llama a un servicio RPC, crea un objeto que encapsula la llamada pendiente, devuelve ese objeto y luego, cuando regresa el RPC, uno de los cierres result
o fault
se llama, y dado que todavía tienen referencias al alcance como estaba cuando se realizó la llamada RPC, pueden activar los métodos en la llamada pendiente/respuesta diferida.
En el comando se vería así:
public function execute( ) : void {
var deferredResponse : DeferredResponse = dao.deleteThing("3");
deferredResponse.addEventListener(ResultEvent.RESULT, onResult);
deferredResponse.addEventListener(FaultEvent.FAULT, onFault);
}
o bien, podrías repetir el patrón, teniendo el execute
El método devuelve una respuesta diferida propia que se activaría cuando se active la respuesta diferida que el comando recibe del DAO.
Pero.No creo que esto sea particularmente bonito.Probablemente podrías hacer algo mejor, menos complejo y menos complicado utilizando uno de los muchos marcos de aplicaciones que existen para resolver más o menos exactamente este tipo de problema.Mi sugerencia sería Compañero.
Otros consejos
Muchas de las clases Flex RPC, como RemoteObject
, HTTPService
, etc.devolver AsyncToken
s cuando los llamas.Parece que esto es lo que buscas.Básicamente el AsyncToken
encapsula la llamada pendiente, lo que permite registrar devoluciones de llamada (en forma de IResponder
instancias) a una llamada específica.
En el caso de HTTPService
, cuando usted llama send()
un AsyncToken
se devuelve, y puede usar este objeto para rastrear la llamada específica, a diferencia del ResultEvent.RESULT
, que se activa independientemente de qué llamada sea (y las llamadas pueden llegar fácilmente en un orden diferente al de su envío).
AbstractCollection es la mejor manera de lidiar con objetos persistentes en Flex/AIR.GenericDAO proporciona la respuesta.
DAO es el objeto que logra realizar la operación CRUD y otras operaciones comunes que se realizarán sobre un ValueObject (conocido como POJO en Java).GenericDAO es una clase DAO reutilizable que se puede utilizar de forma genérica.Meta:
En Java IBM GenericDao, para agregar un nuevo DAO, los pasos a hacer es simplemente, agregar un ValueObject (POJO).Agregue un archivo de mapeo hbm.xml para el objeto de valor.Agregue el archivo de configuración Spring de 10 líneas para DAO.
De manera similar, en AS3 Proyecto Swiz DAO.Queremos alcanzar el mismo nivel de logro.
Modelo GenericDAO del lado del cliente:Como estábamos trabajando en un lenguaje del lado del cliente, también deberíamos administrar una colección de objetos persistentes (para cada objeto de valor).Uso:Fuente:http://github.com/nsdevaraj/SwizDAO