Prevención de Envíos Duplicados de Peticiones Ajax

No se recomienda utilizar variables externas para bloquear o modificar el estado de los botones debido a las siguientes dificultades:

  • Requiere comprender las diferencias entre eventos success, complete, error y timeout, y registrar los correctos; un error haría que la funcionalidad dejara de estar disponible
  • Inevitablemente requiere registrar un evento complete adicional comparado con el flujo normal
  • El código de restauración del estado fácilmente se mezcla con código no relacionado

Se recomiendan métodos de consulta activa del estado (A, B, usando jQuery como ejemplo) o funciones utilitarias (C, D) para eliminar operaciones duplicadas:

A. Envío Exclusivo

Solo permite una operación de envío simultánea, y hasta que se complete no se permite otra.

modulo.enviar = function() {
  if (this.promesa_.state() === 'pending') {
    return
  }
  return this.promesa_ = $.post('/api/guardar')
}

B. Envío Codicioso

Envíos ilimitados donde solo cuenta la última operación; se debe proporcionra retroalimentación inmediata de la última operación, siendo irrelevantes los resultados anteriores.

modulo.enviar = function() {
  if (this.promesa_.state() === 'pending') {
    this.promesa_.abort()
  }
  // implementación
}

Ejemplo: botones de "me gusta"/"no me gusta" donde la retroalimentación inmediata mejora la experiencia de usuario y reduce la carga del servidor.

C. Envío Controlado

El intervalo entre dos envíos válidos siempre será mayor o igual a un tiempo específico; envía a frecuencia constante.

modulo.enviar = throttling(150, function() {
  // implementación
})

Si el cliente envía 10 peticiones cada 100ms, este módulo solo procesará 6 (cada una separada por 150ms). Útil para eventos como resize, scroll o mousemove.

D. Envío Perezoso

Requiere que el intervalo entre envíos sea mayor a un tiempo específico para que sean válidos.

modulo.enviar = debounce(150, function() {
  // implementación
})

Ejemplo: guardado automático en editores que ignora pulsaciones rápidas consecutivas.

E. Envío con Memoria

var rastrear = memoizar(function(url) {
  return $.post('/rastreador', { 'url': url })
})

Para los mismos parámetros, siempre retorna resultados idénticos. Ejemplo: editor que obtiene información de enlaces sin repetir peticiones para URLs idénticas.

F. Envío Acumulativo

var solicitud = crearPila(5, function() {
    $.post('/', { lista: JSON.stringify([].slice.call(arguments)) })
})

// Envío consecutivo
solicitud({b:1}), solicitud({b:2}), solicitud({b:3}), solicitud({b:4}), solicitud({b:5})
/* POST =>
lista:[{"b":1},{"b":2},{"b":3},{"b":4},{"b":5}]
 */

Implemnetación de ejemplo:

var crearPila = function(cantidad, alFiltrar, alValor) {
  var valores = [], id = function(valor) { return valor }
  return function(valor) {
    valores.push((alValor || id).apply(this, arguments))
    if (valores.length === cantidad) {
      alFiltrar.apply(this, valores)
      valores = []
    }
  }
}

G. Envío Muestreado

cargadoAuto.escuchar(fuentes, 'siguiente', muestrear(3, function() {
  this.activar()
}))

Si muestrear es una función de selección fija (elige 1 de n), funciona así:

O-O-X-O-O-X

Para aplicaciones de carga automática que requieren (dos automáticas, una manual):

X-X-O-X-X-O

Se puede definir una función de selección configurable:

opciones { muestrear: (n) => n % 3 !== 0 }

Después de cada carga, de cada tres intentos, dos activarán carga automática.

Etiquetas: AJAX jQuery JavaScript debounce throttle

Publicado el 8-20 15:06