Fundamentos de Ext 4

Manejo de Errores Más videos

Descripción del tema

En este tutorial veremos como crear una clase para manejar los errores en las peticiones Ajax que realicemos a nuestro servidor. Esto nos permitirá concentrar toda la lógica en una sola clase que podremos mantener de una manera más sencilla.

Estandarizando las respuestas del servidor

Es muy importante definir un estandar para todas las respuestas del servidor, ya sea en caso de éxito o en caso de errores, debemos definir alguna manera de comunicarle al cliente que algo ha fallado en el servidor, para este ejemplo definiremos las siguientes respuestas para éxito y para fallo.

//para el caso de éxito
{
    "control" : {
        "success" : true
    },
    "output" : {
"users" : [{ "id" : 1, "name" : "John", "lastname": "Doe", "dob" : "1980-05-21 17:23:03" },{ "id" : 2, "name" : "Susan", "lastname": "Smith", "dob" : "1980-10-16 17:23:03" },{ "id" : 3, "name" : "Peter", "lastname": "File", "dob" : "1983-08-03 17:23:03" }] } }
//para el caso de errores
{
    "control" : {
        "success" : false,
        "errors"  : [{
            "code"    : 404,
            "message" : "El recurso no se encontro en este servidor."
        }]
    },
    "output" : {}
}

Para este ejemplo definimos el objeto control que nos define si la petición fue exitosa o no, la propiedad success es la responsable de indicarnos esto, en caso de error se regresa un arreglo con los errores que se ocasionaron, pueden ser de validación o cualquier otro tipo de error, estos mensajes los podemos mostrar al usuario final si es necesario.

Si la respuesta es exitosa entonces el objeto output contendrá la información solicitada, en este ejemplo es un arreglo de usuarios pero podría contener cualquier cosa.

Clase abstracta

En el tema anterior vimos que la clase Ext.data.Connection es la responsable de realizar las peticiones Ajax, por lo tanto si queremos agregar código para manejar los errores que nuestro servidor nos estará enviando debemos extender de esa clase.

Ext.define('MyApp.abstract.data.Connection',{
    extend      : 'Ext.data.Connection'
});

Lo primero que haremos será sobre-escribir el método request para poder definir nuestros propios callbacks de éxito y fallo donde manejaremos los errores de manera adecuada.

Ext.define('MyApp.abstract.data.Connection',{
    extend      : 'Ext.data.Connection',

    request     : function(options){
        options.originalCallbacks = {  //step 1
            scope   : options.scope || this,
            success : options.success || Ext.emptyFn,
            failure : options.failure || Ext.emptyFn
        };

        options.scope = this;   //step 2
        options.success = this.successCallback;
        options.failure = this.failureCallback;

        this.callParent([options]);   //step 3
    }
});
  • En el paso 1 creamos un objeto llamado originalCallbacks donde almacenaremos temporalmente los callbacks originales ya que los necesitamos llamar más adelante.
  • En el paso 2 sobre-escribimos los callbacks originales con las funciones que necesitamos ejecutar para manejar las respuestas de manera adecuada.
  • En el paso 3 ejecutamos el método request de la super clase, el cual ejecuta la petición Ajax.

Lo siguiente es definir la función successCallback la cual se encargará de manejar el caso de éxito y la función failureCallback que se encargará de manejar el caso de fracaso.

Ext.define('MyApp.abstract.data.Connection',{
    extend      : 'Ext.data.Connection',

    request     : function(options){
        //...
    },

    successCallback : function(response,options){
        console.log('success', options);
    }    

    failureCallback(response,options){
        console.log(options);
    }
});
Por el momento solo vamos a imprimir el objeto options en la consola y vamos a crear el HTML para probar el ejemplo. Vamos a llamar el HTML 02-custom-ajax.html y vamos a importar la clase que acabamos de crear: Connection.js.
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>Custom Ajax</title>
    <link rel="stylesheet" href="../ext-4.2.1/resources/css/ext-all.css"/>
    <script type="text/javascript" src="../ext-4.2.1/ext-all-dev.js"></script>
    <script type="text/javascript" src="Connection.js"></script>

    <script type="text/javascript">
        
    var Ajax = Ext.create('MyApp.abstract.data.Connection');  //paso 1

    Ajax.request({  //paso 2
        url : 'serverside/errores.json',
        success : function(data){  //paso 3
            console.log('Success en el Ajax');
        },
        failure : function(){
            console.log('Failure en el Ajax');
        }
    });


    </script>
</head>
<body>

</body>
</html>
  • En el paso 1 creamos una instancia de la clase Connection.
  • En el paso 2 usamos el método request de la clase para hacer una petición a la url que le asignamos.
  • En el paso 3 definimos el callback de success y failure que por el momento solo imprimen un mensaje en la consola. Estos callbacks no van a ser ejecutados ya que en la clase de Connection los hemos sobre-escrito, aunque como en los callbacks de esa clase estamos imprimiendo lo que tiene el objeto options, vamos a poder ver las funcione originales.
Si probamos el ejemplo en el navegador vamos a ver que se imprimió el objeto options y en la propiedad originalCallbacks vamos a ver las funciones originales de success y failure
Vamos a cambiar el contenido del método successCallback de la clase Connection, quitamos la impresión a la consola y escribimos el siguiente código:
successCallback : function(response,options){
    try{
        info = Ext.decode(response.responseText);   //paso 1 
    }catch(e){
        info = {control:{success:false}};
    }

    if(info.control.success){ //paso 2
        options.originalCallbacks.success.call(options.originalCallbacks.scope,info);
    }else{
        this.failureCallback(response,options);  //paso 3
    }
},
  • En el paso 1 estamos decodificando lo que tiene la propiedad responseText, que es básicamente es la respuesta del servidor en formato texto. Lo que hace el método decode es convertir ese texto a objetos de JavaScript. Es necesario que esta parte vaya dentro de un bloque try/catch en caso de que la respuesta del servidor no sea en formato Json, ya que el método decode fallaría y se ejecutaría el método catch. En el método catch solo vamos a definir que success es falso en el objeto control.
  • En el paso 2 checamos si la propiedad success es verdadera para poder ejecutar el callback original. Le estamos pasando como parámetro el scope y la respuesta del servidor.
  • En el paso 3 si la propiedad success es falsa entonces ejecutamos el método failureCallback que vamos a definir en un momento.
Ya que estamos mandando la respuesta del servidor como parámetro, necesitamos agregar ese parámetro al callback original. En el archivo HTML vamos a modificar la función success:
success : function(data){
    console.log('Success en el Ajax',data.output.users);
},
De esta forma estamos imprimiendo la respuesta del servidor en objetos JavaScript. 
Ya que definimos el callback de success es necesario definir el callback de failure en la clase Connection.
failureCallback : function(response,options){
    var info,error;
    try{
        info = Ext.decode(response.responseText);  //paso 1
    }catch(e){
        info = {control:{success:false}};
    } 

    if(info.control.errors){  //paso 2
        for(var i=0,len=info.control.errors.length;i<len;i++){
            error = info.control.errors[i];  //paso 3

            if(error.code === 401){
                this.fireEvent('sessionexpired',error);
            }else{
                this.fireEvent('ajaxerror',error);
            }
                           
        }
    }else{  //paso 4
        error = {};
        switch(response.status){
            case 0   : error.message = 'Verifica tu conexión, es posible que este fallando.';
                    break;
            case 401 : error.message = 'Tu sesión ha expirado.';
                  this.fireEvent('sessionexpired',error);
                  break;
            case 403 : error.message = 'No tienes permisos para acceder este recurso.';
                  break;
            case 404 : error.message = 'Recurso no encontrado';
                  break;
            case 500 : error.message = 'Error en el servidor';
                  break;
            default : error.message = response.statusText;
        }
        this.fireEvent('ajaxerror',error);
    }

    options.originalCallbacks.failure.call(options.originalCallbacks.scope,error);  //paso 5
}
  • En el paso 1 decodificamos la respuesta del servidor a objetos JavaScript dentro de un bloque try/catch por si el servidor nos manda un error que no sea Json.
  • En el paso 2 verificamos si existe el objeto errors dentro del objeto control, si existe significa que el servidor regresó los errores de manera adecuada en un arreglo.
  • En el paso 3 estamos iterando el arreglo errors y por cada error que haya se dispara un evento. Si el error ocurrió porque terminó la sesión disparamos el evento sessionexpired, de lo contrario disparamos el evento ajaxerror.
  • En el paso 4 utilizamos un switch donde estamos diferenciando los tipos de errores que nos mandó el servidor utilizando el status de la respuesta; por cada error especificamos un mensaje. Al finalizar el bloque switch disparamos el evento de ajaxerror.
  • En el paso 5 simplemente estamos ejecutando el callback original del failure.
Antes de probar el ejemplo vamos a crear un listener del evento ajaxerror en el archivo HTML. Agregamos el siguiente código antes de hacer el request:
MyApp.Ajax.on('ajaxerror',function(error){
      Ext.Msg.alert('Error',error.message);
});
Básicamente lo que hicimos en el código anterior es escuchar el evento y mandar un mensaje de alerta cada vez que se genere un error.
Ahora si podemos probar el ejemplo. Vamos a hacer que se ejecuten los callbacks de failure, para hacer eso vamos a cambiar en el archivo errores.json, la propiedad:
"success" : false
Al ejecutar el ejemplo nos debe aparecer un mensaje en la pantalla con el mensaje de error. Este ejemplo nos muestra que podemos crear nuestro propio sistema de errores con Ext.

Te gustaría recibir más tutoriales como este en tu correo?

Este tutorial pertenece al curso Fundamentos de Ext 4, te recomiendo revises el resto de los tutoriales ya que están en secuencia de menor a mayor complejidad.

Si deseas recibir más tutoriales como este en tu correo te recomiendo registrarte al curso, si ya eres miembro solo identifícate y registrate al curso, si no eres miembro te puedes registrar gratuitamente!

Si no gustas registrarte en este momento no es necesario! Aún así puedes recibir los nuevos tutoriales en tu correo! Jamás te enviaremos Spam y puedes cancelar tu suscripción en cualquier momento.

¿Olvidaste tu contraseña?

2Comentarios

  • Avatar-6 salvador.vidal 29/10/2013

    Tengo problemas en entender bien la linea: options.originalCallbacks.success.call(options.originalCallbacks.scope,info); El concepto de scope lo entiendo, pero no entiendo que le estoy pasando aqui y que va a hacer con ello Ext

    • Avatar-11 Crysfel Villa 26/02/2014

      Esa línea es simplemente la ejecución del callback que se definió al hacer el request: Ext.request({ ... success : function(){...} }); En esta línea es donde se ejecuta el success del request.

    Instructor del curso

    Crysfel3

    Autor: Crysfel Villa

    Es Ingeniero de Software con más de 7+ años de experiencia profesional, durante 5 de los cuales ha estado desarrollando con Ext JS. Es autor del libro "Learning Ext JS 4" publicado por Packt Publishing en enero del 2013.

    Descarga video Descarga Código Fuente Ver Demostración

    Regístrate a este curso

    Este tutorial pertenece al curso Fundamentos de Ext 4, revisa todos los tutoriales que tenemos en este mismo curso ya que están en secuencia y van de lo más sencillo a lo más complicado.

    Tendrás acceso a descargar los videos, códigos y material adicional.

    Podrás resolver los ejercicios incluidos en el curso así como los Quizzes.

    Llevarás un registro de tu avance.