Actualizar un div con ajax cuando haya cambio

publicado por: user95232

Quiero llegar a hacer un div que recargue solo cuando halla una modificación en la base de datos actualmente tengo esto así, si me pueden ayudar se los agradecería es para un sistema de turnos que estoy haciendo

<?php

$result = $mysqli->query("SELECT * FROM  `turnos` ORDER by `turno` desc limit 1" ); 
$row = $result->fetch_row(); 

  echo '<script type="text/javascript">
  swal({ title: "siguiente turno : '.$row[0].'", 
  text: "Se envio correctamente", 
  type: "success",
  showConfirmButton: false,
  timer: 2000
});
 </script>'; 

introducir la descripción de la imagen aquí

Este es el ajax:

 <script>
    setInterval(function() {
$('#turnos').load('./ajax/turnos.php');`// Selector de la div y el fichero a refrescar

}, 1000); // Temporizador que ejecuta el refresco cada 1 segundos
</script>

div

<div id="turnos"></div>

solución

Lo que estás haciendo es básicamente correcto. Una base de datos como MySQL no es “reactiva” como para gatillar alertas cuando ocurren cambios. Lo que tú estás haciendo es una especie de long-polling.

Sin embargo,, creo que lo estás enfocando mal. El backend no tiene por qué imprimir un script. De hecho me parece muy mala idea.

El backend sólo debiera responderte con un objeto de la forma

{turno: 5}

Y en el front, tú mismo llamar a SweetAlert si es que la respuesta del backend es distinta a la anterior (que guardas en una variable);

En otras palabras, en tu backend:

<?php

$result = $mysqli->query("SELECT * FROM `turnos` ORDER by `turno` desc limit 1" ); 
$row = $result->fetch_row(); 

echo json_encode(['turno'=>$row[0]]);

Y en el frontend:

var turno_actual=0;

function desplegarAlerta() {
   // despliego la alerta desde el front
   swal({
    title: "siguiente turno : " + turno_actual,
    text: "Se envio correctamente",
    icon: "success",
    button: true
  });
}

function refrescaTurno() {

   $.ajax({
     url: "./ajax/turnos.php",
     dataType:'json' // parseo la respuesta como objeto
   }).then(function(response) {
      // sólo lo ejecutas si el turno cambió
      if(response.turno != turno_actual) {
         turno_actual=response.turno;
         desplegarAlerta();
      }
      window.setTimeout(refrescaTurno,2000);
   });

}

refrescaTurno();

Nótese que me tomé de la idea de Ivanrangel para gatillar el nuevo llamado una vez que el backend ha respondido. Si pones un intervalo arbitrario y el backend demora más que éste, vas a encolar llamados.

Te dejo un ejemplo en donde, a falta de llamadas ajax puse una función que me genera un número aleatorio, el cual determina si se incrementó el turno o si se ha mantenido igual. Si el nuevo turno es igual al existente, escribo en la consola que no hay cambios.

PD: no estoy usando para nada el div que tú estabas llenando. Ignoro si tiene alguna relevancia.

PD2: tú estabas definiendo el SweetAlert para autocerrarse luego de 2 segundos. Yo le quité ese parámetro porque en tu ejemplo no tenía sentido (polling cada 1 segundo, nunca se cumplían los 2 segundos para autocerrarse)

_x000D_

_x000D_

var last_turno = 1,_x000D_
  intervalo;_x000D_
  _x000D_
function getTurno() {_x000D_
  return new Promise(function(resolve,reject) {_x000D_
      var random=parseInt(7*Math.random(),10);_x000D_
      if(random>3) {_x000D_
        window.setTimeout(function() {_x000D_
          resolve({turno:last_turno+1});_x000D_
        },500);_x000D_
      } else {_x000D_
         window.setTimeout(function() {_x000D_
          resolve({turno:last_turno});_x000D_
        },500);_x000D_
      }_x000D_
  });_x000D_
}_x000D_
_x000D_
function displayTurno(turno) {_x000D_
  console.log('El nuevo turno es '+last_turno);_x000D_
  swal({_x000D_
    title: "siguiente turno : " + turno,_x000D_
    text: "Se envio correctamente",_x000D_
    icon: "success",_x000D_
    button: true_x000D_
  });_x000D_
}_x000D_
_x000D_
function comenzarIntervalo() {_x000D_
  displayTurno(last_turno);_x000D_
  intervalo = setInterval(function() {_x000D_
    getTurno().then(function(response) {_x000D_
      if(response.turno !== last_turno) {_x000D_
        last_turno=response.turno;_x000D_
        displayTurno(last_turno);  _x000D_
      } else {_x000D_
        console.log('No ha cambiado el turno');_x000D_
      }_x000D_
    });_x000D_
    _x000D_
  }, 5000);_x000D_
_x000D_
}_x000D_
_x000D_
jQuery(document).ready(function() {_x000D_
  jQuery('#iniciar').on('click', function() {_x000D_
    jQuery('#terminar').removeAttr('disabled');_x000D_
    jQuery('#iniciar').attr('disabled', 'disabled');_x000D_
    comenzarIntervalo();_x000D_
  });_x000D_
  jQuery('#terminar').on('click', function() {_x000D_
    jQuery('#iniciar').removeAttr('disabled');_x000D_
    jQuery('#terminar').attr('disabled', 'disabled');_x000D_
    clearInterval(intervalo);_x000D_
  });_x000D_
});

_x000D_

.swal-icon {_x000D_
float:left;_x000D_
margin-left:50px;_x000D_
}

_x000D_

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>_x000D_
<script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script>_x000D_
_x000D_
<div id="turnos"></div>_x000D_
_x000D_
<input type="button" value="terminar el refresco" id="terminar" disabled="disabled">_x000D_
<input type="button" value="empezar a refrescar" id="iniciar">

_x000D_

_x000D_

_x000D_

Respondido por: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *