2012-01-16 32 views
8

En realidad, la pregunta es tan simple como dice el tema. ¿Hay alguna manera de dar a los diferentes manejadores ajax una prioridad mayor/menor (lo que significa aquí, que van a disparar antes)?jQuery - establecer la prioridad del controlador Ajax

¿Qué quiero decir? Bueno, tengo que lidiar con una aplicación web bastante grande. Toneladas de solicitudes de Ajax se disparan en diferentes módulos. Ahora, mi objetivo es implementar un mecanismo simple de tiempo de espera de sesión. Cada solicitud envía el ID de sesión actual como parámetro, si el ID de sesión ya no es válido, mi script backend devuelve la solicitud con un conjunto de encabezado de respuesta personalizado (value es un uri).

Así que estoy básicamente va como esto

window.jQuery && jQuery(document).ajaxComplete(function(event, xhr, settings) { 
    var redirectto = xhr.getResponseHeader('new_ajax_location'); 
    if(redirectto) { 
     location.href = redirectto; 
    } 
}); 

Este trabajo lo hace como un encanto, por supuesto, pero mi problema es que este evento global ajax realidad tiene que ser despedido primero el 100% del tiempo, lo cual no es el caso. Algunos de los gestores de solicitudes ajax originales arrojarán un error debido a datos faltantes o inesperados, en ese caso, el controlador global nunca se ejecutará.

Ahora, sería un poco feliz si no tuviera que pasar por cada controlador de solicitud y hacerlo a prueba de fallas para las respuestas de datos de sesión no válidos. Preferiría mucho más hacer el trabajo en un lugar en particular. Pero, ¿cómo puedo asegurarme de que mi manejador global se ejecute primero?

+0

Probablemente utilizando la devolución de llamada 'onSuccess'. – Stefan

+0

@Stefan: Tendría que capturar todos los resultados posibles para una solicitud, por lo que 'completo 'es bastante bueno. Pero también verifiqué establecer 'success' y' error' manualmente, desafortunadamente con el mismo comportamiento. – jAndy

+0

Relacionados con http://stackoverflow.com/questions/290254/how-to-order-events-bound-with-jquery, ya que los eventos AJAX se implementan utilizando el sistema de eventos principales. –

Respuesta

1

Si le entiendo correctamente, quiere agregar su propia devolución de llamada a las solicitudes json en todas partes. Podría usar el gancho ajaxPrefilter.

$.ajaxPrefilter(function(options, originalOptions, jqXHR) { 
     options.complete = function (jqXHR2, settings) { 
      var redirectto = jqXHR2.getResponseHeader('new_ajax_location'); 
      if(redirectto) { 
       location.href = redirectto; 
      } 
     } 
    }); 

También puede cambiar las opciones allí para agregar el ID de sesión a los parámetros de solicitud.

0

jQuery le permite "parchar" sus métodos, como .post/.ajax.

Es posible que pueda aplicar un parche a los métodos apropiados para que su evento especial AJAX siempre se active antes del que su código desea llamar.

Esto es un "código pseudo-jQuery" que debería ayudarlo a comenzar. Dudo que funcione como está, pero demuestra el concepto básico y debería ayudarte a empezar.

(function($){ 
    var originalPost = $.post; 
    var calledSpecialOne = false; 
    $.post = function(url, data, success, dataType) { 
     if (!calledSpecialOne) { 
      originalPost(... your special AJAX query ...).then(function() { 
      originalPost(url, data, success, dataType); 
      } 
      calledSpecialOne = true; 
     } else { 
      originalPost(url, data, success, dataType); 
     } 
    } 
})(jQuery); 

Lo anterior se basa en alguna otra, no relacionado, código que tengo probados, lo que hace $ each() trabajan para las matrices indefinidos/null):

(function($){ 
    var originalEach = $.each; 
    $.each = function(collection, callback) { 
     return collection? originalEach(collection, callback) : []; 
    } 
})(jQuery); 

Tenga en cuenta que muchas expuestos JQuery también llama internamente a las funciones, así que ten MUY cuidado usando este truco; puede romper una parte diferente de jQuery o causar otro problema. En el caso de las funciones AJAX, probablemente debería parchear la función más interna solamente, para evitar la recursión infinita. (FWIW, no he encontrado ningún efecto secundario para el parche $ .each() hasta ahora).

+0

incluso si me gusta el principio de perforación de patos, no me gusta en esta situación particular. Tendría que aplicarle un parche a cada rutina de ajax disponible, o simplemente aplicar '.ajax()', pero esta vez no me atrevo realmente. Pero es posible que no tenga otra opción si no hay una posibilidad oficial de modificar órdenes de llamadas. – jAndy

0

No estoy seguro de si esto es incluso lo que querías decir, pero pensé que podría necesitarlo como un punto de todos modos.

Parchea la función ajax de jQuery para aceptar un objeto con la propiedad priority. Si no hay una prioridad establecida, su prioridad es 1 (prioridad más alta 0). Si hay una prioridad, hace una de dos cosas. Si la prioridad es algo así como 5, verifica si se llamó a la llamada ajax con la prioridad previa (en este caso 4). Si no, lo agrega a un conjunto de llamadas ajax con esa prioridad (en este caso 5).Si se ha llamado a la prioridad anterior, llama a la solicitud normalmente. Cuando se llama a una solicitud con una prioridad, llama a cualquier solicitud saliente con la siguiente prioridad más alta.

En otras palabras, si no hay prioridad, espera a que la prioridad 0, si no es una prioridad, espera a que la prioridad debajo de él para ser llamado. Si desea que las llamadas que no tienen prioridad para ser enviados inmediatamente, comente la línea con el comentario que puso diciendo default action?

(function($){ 
     var oldAjax=$.ajax; 
     var outgoing=[]; 
     var sent=[]; 
     $.ajax=function(url, settings) { 
      var pr = (typeof url==='object'?url:settings).priority; 
      pr = pr===undefined ? 1 : pr; // default action? 
      if(pr!==undefined){ 
       if(pr==0 || sent[pr-1]!==undefined){ 
        oldAjax(url,settings); 
        sent[pr]=true; 
        if(outgoing[pr]){ 
         var rq=outgoing[pr].splice(0,1)[0]; 
         $.ajax(rq[0],rq[1]); 
        } 
        if(outgoing[pr+1]){ 
         var rq=outgoing[pr+1].splice(0,1)[0]; 
         $.ajax(rq[0],rq[1]); 
        } 
       } 
       else{ 
        if(outgoing[pr]!==undefined){ 
         outgoing[pr].push([url,settings]); 
        } 
        else{ 
         outgoing[pr]=[[url,settings]]; 
        } 
       } 
      } 
      else{ 
       oldAjax(url, settings); 
      } 
     }; 
    })(jQuery); 

Parches para get y post. Deberá incluir esos argumentos adicionales o cambiarlos usted mismo para que la prioridad funcione con las solicitudes post y get. Esto es directamente desde jQuery 1.7, excepto por el argumento adicional, y las dos líneas a las que agregué comentarios.

jQuery.each([ "get", "post" ], function(i, method) { 
    jQuery[ method ] = function(url, data, callback, type, priority) { 
     // shift arguments if data argument was omitted 
     if (jQuery.isFunction(data)) { 
      priority = type; // my change 
      type = type || callback; 
      callback = data; 
      data = undefined; 
     } 

     return jQuery.ajax({ 
      type: method, 
      url: url, 
      data: data, 
      success: callback, 
      dataType: type, 
      priority: priority // my change 
     }); 
    }; 
}); 

I fijó un ejemplo aquí: http://jsfiddle.net/tk39z/

De hecho, me creé algunas peticiones ajax orientación de Google, para que pueda comprobar el panel de la red en Chrome para ver las solicitudes.

0

que recientemente puso en marcha algo muy similar a la funcionalidad que creo que usted está buscando.

He definido un filtro en el lado del servidor para comprobar si una sesión válida y, si no, devuelve un error 401 con el texto de estado personalizado para un detalle de error más específico.

Las llamadas ajax he realizado en estas páginas se escribieron en la convención normal usando el atributo 'éxito'.

Para situaciones en las que había un error, he añadido una devolución de llamada global a la función de error que pondría a prueba para el error específico y reorientar en consecuencia. como:

$(document).ajaxError(function(e, xhr) { 
    var redirectto = xhr.getResponseHeader('new_ajax_location'); 
    if(redirectto) { 
     location.href = redirectto; 
    } 
}); 
Cuestiones relacionadas