2011-03-07 9 views
16

A partir de jQuery 1.5, los métodos ajax ahora manejan correctamente 304 respuestas no modificadas llamando al controlador success(), según las especificaciones W3C para XMLHTTPRequest. Esto permite que su aplicación trate la solicitud como exitosa, incluso si el servidor no devolvió ningún dato (porque ya tiene los últimos datos almacenados en caché).Manera correcta de manipular 304 no modificada en jQuery ajax

Para una normal (sin caché) petición GET, el manejador de éxito se llama con los siguientes argumentos:

  • datos: {los datos del servidor}
  • estado: OK
  • jqXHR:
    • estado: 200
    • statusText: OK
    • responseText: {los datos del servidor}

Para una petición GET en caché, el controlador de éxito se llama con los siguientes argumentos:

  • datos: indefinido estado
  • : notmodified
  • jqXHR:
    • estado : 304
    • statusText: no modificado
    • responseText: {los datos de la caché}

(al menos, esta es la forma en que se devuelve en IOS 4.2, para una aplicación Web que utiliza el caché de la aplicación a través de un archivo de manifiesto. Supongo que esto es coherente para el almacenamiento en caché general del navegador en la mayoría de las plataformas/navegadores).

Puede ver que el argumento "datos" solo se rellena si la solicitud fue 200 correcta; donde como jqXHR.responseText siempre se rellena con datos, independientemente de si esos datos provienen del servidor (200 OK) o de la caché (304 Not Modified).

Dado que, en la mayoría de las solicitudes GET, su controlador de éxito va a querer hacer algo con los datos que obtuvo independientemente de su procedencia, parece que lo más lógico para su código de éxito es utilizar siempre jqXHR.responseText, en lugar de hacer algo como esto:

if ("notmodified" === status) { 
    // do something with jqXHR.responseText 
} else { 
    // do something with data 
} 

O hay alguna vez un caso cuando jqXHR.responseText no estaría poblada en el manejador de éxito, pero los datos arg sería?

Tengo que pasar por mi base de código y cambiar todos los manejadores de éxito (anteriormente estaba en jQuery 1.4.2, que siempre devolvía datos, incluso desde la caché); así que solo quiero asegurarme de que lo estoy manejando de la manera correcta. (No quiero llegar al final y luego darse cuenta de que debería haberlo hecho de otra manera).

Respuesta

7

Acabo de descubrir el defecto obvio en mi pregunta .... Estaba asumiendo que los datos siempre eran de texto, por lo que usar jqXHR.responseText en lugar del argumento de datos tenía sentido.

Pero en el caso de que el tipo de datos sea JSON, JSONP, secuencia de comandos, etc ... si los datos devueltos en una respuesta 304 No modificada vuelven como indefinidos, necesitaría convertir el texto jqXHR.responseText de una cadena a el tipo deseado primero, ej.

if (data === undefined) { 
    data = $.parseJSON(jqXHR.responseText); 
} 

... y usted sólo quiere hacer esto (potencialmente costosa) de conversión cuando se necesita realmente.

Un poco tiene sentido ahora que lo pienso ... de datos siempre va a ser lo que regresó desde el servidor (que en algunos casos podría no ser definida para un 304 ... por ejemplo. El servidor podría devuelve texto adicional/html); que le permite al desarrollador la flexibilidad de elegir lo que quiere hacer en el caso de un 304, ej.

  • mostrar la respuesta del servidor (si lo hay)
  • Uso del jqXHR.responseText
  • hacer algo completamente distinto ...
+1

Actualmente estoy lidiando con este problema en un proyecto ... algo sorprendente que jQuery no rellene automáticamente el parámetro de datos por usted. No estoy de acuerdo con su lógica ... Estoy bastante seguro de que el estándar HTTP requiere un cuerpo de respuesta vacío para 304 respuestas no modificadas, por lo que el servidor no debe enviar datos adicionales ... no debería haber cualquier ambigüedad –

+0

En mi caso, jqXHR.responseText no está definido con un texto de respuesta también :( – drogon

4

Dependiendo del contexto, puede utilizar el parámetro cache a la solicitud de ajax:

$.ajax({ 
    url: ".....", 
    dataType: "json", 
    type: "GET", 
     cache: false, 
    contentType: "application/json", 
     success: function (data, textStatus) { 
      console.log("RECV: " + data); 
     } 
    }); 

Eso funciona para mí.

Cuestiones relacionadas