2011-02-24 10 views
14

Estoy creando una utilidad ajax para interactuar con mis métodos de servidor. Me gustaría aprovechar jQuery 1.5+ métodos diferidos del objeto devuelto de la llamada jQuery.ajax(). La situación está siguiendo.jQuery jqXHR - cancelar llamadas encadenadas, desencadenar cadena de error

  1. El método serverside siempre devuelve un objeto JSON:

    { success: true|false, data: ... }

  2. La utilidad del lado del cliente inicia la llamada AJAX como esta

    var jqxhr = $.ajax({ ... });

  3. Y el problema área:

    jqxhr.success(function(data, textStatus, xhr) { 
        if(!data || !data.success) { 
         ???? // abort processing, trigger error 
        } 
    }); 
    return jqxhr; // return to caller so he can attach his own handlers 
    

Así que la pregunta es cómo cancelar la invocación de todas las personas que llaman anexa éxito devoluciones de llamada de un disparador de su controlador de errores en el lugar mencionado con ?????

La documentación dice que las listas de invocación de funciones diferidas son FIFO, por lo que mi controlador de éxito es definitivamente el primero.

Respuesta

29

(ACTUALIZACIÓN:. Tenga en cuenta que actualmente promesas jQuery no son compatibles con la Promises/A+ specification - más información en this answer)

En su función de donde se crea la petición AJAX también se puede crear un objeto diferido y devolver una promesa a la persona que llama después de la unión de su determinación y rechazar las devoluciones de llamada a las funciones apropiadas de la solicitud $ .ajax con un poco de verificación de datos personalizados, como esto:

function makerequest() { 

    var deferred = $.Deferred(); 
    var promise = deferred.promise(); 

    var jqxhr = $.ajax({ 
     // ... 
    }); 

    jqxhr.success(function(data, status, xhr) { 
     if (!data || !data.success) { 
      deferred.reject(jqxhr, 'error'); 
     } else { 
      deferred.resolve(data, status, xhr); 
     } 
    }); 

    jqxhr.error(function(jqXHR, status, error) { 
     deferred.reject(jqXHR, status, error); 
    }); 

    return promise; 
} 

Ahora cualquiera habrá capaz de utilizarlo como cualquier promesa como esto a su función:

var request = makerequest(); 

request.done(successCallback); 
request.fail(errorCallback); 

O incluso:

makerequest().then(successCallback, errorCallback); 

Si también añadir lo siguiente:

promise.success = promise.done; 
    promise.error = promise.fail; 

entonces su interlocutor deberá (quizás más familiar) interfaz de .success() y .error() como con llamadas $ .ajax() puro:

var request = makerequest(); 

request.success(successCallback); 
request.error(errorCallback); 

(La implementación de .complete() se deja como un ejercicio para el lector.)

ver este demostraciones:

Aquí hay otro ejemplo sacó directamente de un proyecto de trabajo:

function ajax(url, data) { 
    var self = this; 
    var deferred = $.Deferred(); 
    var promise = deferred.promise(); 

    var jqxhr = $.ajax({ 
     url: url, 
     data: JSON.stringify(data), 
     contentType: "application/json; charset=utf-8", 
     dataType: 'json', 
     type: 'POST' 
    }).done(function (msg, status, xhr) { 
     if (!msg || msg.Error) { 
      self.doError(msg.Error); 
      deferred.reject(jqxhr, 'error'); 
     } else { 
      deferred.resolve(msg, status, xhr); 
     } 
    }); 

    return promise; 
} 
+4

** NOTA **: Esta respuesta está fechada en Feb '11, en ese momento jQuery estaba en v1.5. Las mejoras posteriores a jQuery hacen que esta respuesta sea redundante. Desde v1.6, la solución generalmente aceptada habría implicado 'diferido.pipe()' y de v1.8 'diferido.then()', en cuyo punto escribiríamos algo así como 'función makerequest() {return jqxhr.then (función (datos) {return (data && data.success)? jqxhr: $ .Deferred(). reject (nuevo Error ('AJAX data error')). promise();}); } ' –

+0

Tan pronto como comencemos a devolver algo que no es igual a 'jqXHR' (como' $ .Deferred(). Promise' en la respuesta anterior), perdemos el acceso a la función '.abort()' del objeto 'jqXHR' original y podemos No aborte la solicitud antes de que se resuelva, si es necesario. –

Cuestiones relacionadas