Nueva pregunta

Pregunta:

Fecha: 15-04-2018 04:46:31 (En Español)

Ajax anidado | ¿Cómo hacer la espera a las solicitudes de un Ajax dentro de otro?[Resuelta]

Hola comunidad, un saludo.

Estoy tratando de crear un sistema de verificación de dispositivos conectados en red por medio de ICMP (ping). Todo el trabajo con respecto a la verificación lo hace PHP (Funcional). Inicialmente lo que hago con la aplicación es mostrar los registros que simulan ser los dispositivos (dirección ip). Luego con un elemento tipo button capturo el evento click y hago una solicitud ajax, que manda a traer los registros de dipositivos del gestor de base de datos (Todo bien); estos datos los extraigo en un objeto JSON. A continuación, el código PHP. Script: gn.TestingShowUsers.php
<?php
	@session_start();

    #Importar constantes.
    include (@$_SESSION['getConsts']);

    include (PF_CONNECT_SERVER);
    include (PF_SSH);

    $CN = new ConnectSSH();
    $CN->ConnectDB($H, $U, $P, $D, $X);

    $R = $CN->getHostWithOutInterfaces();

    #Esto es lo importante...
    $jsondata = array();
    
    if ($R->num_rows > 0){
   		$jsondata["success"] = true;
   		$jsondata["data"]["message"] = sprintf("Se han encontrado %d registros", $R->num_rows);
   		$jsondata["data"]["hosts"] = array();

   		while ($row = $R->fetch_object())
   			$jsondata["data"]["hosts"][] = $row;
    } else {
    	$jsondata["success"] = false;
    	$jsondata["data"] = array(
    			"message" => "No se encontraron resultados"
    		);
    }

    header('Content-type: application/json; charset=utf-8');
    echo json_encode($jsondata, JSON_FORCE_OBJECT);
    
    exit();
?>
Este código utiliza un par de clases para que todo funcione, lo muestro para que observen la estructura del JSON. La petición Ajax es la siguiente:
var respuesta;

$("#TestingShowUsers").click(function(){
	$.ajax({
		url: "app/Desktop/Root/php/gn.TestingShowUsers.php", 
		type: "post", 
		dataType: "json",
	})
	.done(function(response) {
		respuesta = response;
	})
	.fail(function( jqXHR, textStatus, errorThrown ) {
	     if ( console && console.log ) {
	         console.log( "La solicitud a fallado: " +  textStatus);
	     }
	})

	.then(function(){
		if (respuesta.success){

            $.each(respuesta.data.hosts, function( key, value ) {
                //recorremos los valores de cada dispositivo
                $.each( value, function ( userkey, uservalue) {
                    if (userkey == "ip_host"){
                        //Este lo ocupo para seleccione a una clase que ya está automatizada para aplicarle cambios.
                    	var ClassParent = uservalue.split(".").slice(0,4).join("");

                    	var parametros = {
					        "ip_addr" : uservalue,
					    }

						$.ajax({
							url: "app/Desktop/Root/php/gn.CheckPing.php",
							type: "post",
							data: parametros,
							beforeSend: function() {
                                                                //Código para que el contenedor con la clase automatizada, cargue un loader antes de la ejecución de la petición.
								NProgress.configure({ parent: '.host' + ClassParent });
								NProgress.start();
							}, 
							success: function(data){
                                                                //Que el proceso del loader, deje de continuar porque ya está verificado.
								NProgress.done();
							}
						});
                    }
                });
            });
		}
	});
});


Les expondré el retorno del objeto a JS en petición al script: gn.TestingShowUsers.php.
success: true
data	{…}
message:	Se han encontrado 17 registros
hosts:	{…}
0:	{…}
ip_net: 192.168.100.0/24
ip_host: 192.168.100.1
router: 1
net_next: 192.168.101.0/24
alias: First Router
1:	{…}
ip_net: 192.168.100.0/24
ip_host: 192.168.100.3
router: 0
net_next: -
alias: Evidencia
2:	{…}
ip_net: 192.168.100.0/24
ip_host: 192.168.100.20
router: 0
net_next:	-
alias: Windows XP 100.20
Script: gn.CheckPing.php
<?php
	@session_start();

    #Importar constantes.
    include (@$_SESSION['getConsts']);

	include (PD_DESKTOP_ROOT_PHP_CLASS."/gn.class.ping.php");

    $CD = new CheckDevice();
    #El retorno es 1 o 0. Aunque no tiene importancia porque en JS de momento no hago la verificación.
    echo ($CD->ping($_POST['ip_addr'])) ? "1" : "0";
?>
El en solicitud al script: gn.CheckPing.php no se manda a llamar después del .then. Pero si luego doy otro click en el botón que vuelve a hacer las solcitudes, entonces sí es mandado a llamar, en este caso en el JSON he mostrado 3 registros, lo cual si manda a ejecutar 3 veces el con sus respectivos parámetros, ahí todo bien.

Problema:
El código para cargar el loader, se ejecuta asíncronamente, lo cual corre de una sola vez sin esperar la respuesta de las solicitudes, ya que antes de la solicitud necesito mostrar el loader encima del contendor que representa al dispositivo, luego de haber hecho la verificación, entonces pasaré al siguiente registro del objeto JSON para que haga lo mismo con los demás. Pero el ciclo $.each pasa de un solo toque, no espera que devuelva un resultado en por esa razón, cuando necesito que el primer contenedor del dispositivo presente el loader, lo está presentando en el último contenedor porque ya pasó por todos sin haber verificado.

Espero haberme hecho entender, estaré activo esperando respuesta. Por supuesto, seguiré investigando.

¡Saludos!
Etiquetas: AJAX - HTML - Javascript - Javascript JSON - JQuery - JSON - MySQL - PHP - PHP JSON - Pregunta - Web Votos: 0 - Respuestas: 3 - Vistas: 13 Compartir en: Google Facebook Twitter LinkedIn Link
 

Respuestas:

  • Fecha: 17-04-2018 12:06:19 Todas las acciones AJAX que se ejecutan en el hilo pricipal del navegador son, por defecto, asíncronas.

    Si lo que quieres es que se ejecuten de manera síncrona entonces tienes que utilizar un worker.
      Votos: 1 - Link respuesta
     
  • Fecha: 17-04-2018 14:36:02 Ernesto, gracias por su respuesta, me ha servido para informarme más sobre el asunto.

    He resuelto el problema, aprendí sobre ejecución asíncrona con generadores, promesas y corrutinas; totalmente un mundo que desconocía. Con esa idea de programación, logré enviar y recibir las peticiones al servidor en orden.

    ¡Un saludo!
      Votos: 1 - Link respuesta
     
  • Fecha: 19-04-2018 05:54:12 Por si alguien tiene una situación parecida, acá está una sencilla solución:
    function CheckPingAjax(value, callback) {
        console.log('START execution with value =', value);
        var ip_host = respuesta.data.hosts[value].ip_host;
        var parametros = {"ip_addr" : ip_host}
    
        NProgress.start();
    
        $.ajax({
            url: "app/Desktop/Root/php/gn.CheckPing.php",
            type: "post",
            data: parametros,
            success: function(data){
                NProgress.done();
                callback(value, {ip_host: ip_host, data: data});
            }
        });
    }
    
    function nuevallamada(){
    
        var max_host = respuesta.data.count;
        var i_host = 0;
    
        NProgress.configure({parent: '.host' + respuesta.data.hosts[i_host].ip_host.split(".").slice(0,4).join("")});
        CheckPingAjax(i_host, function callback(value, result) {
    
    
            console.log('END execution with value =', value, 'and result =', result.ip_host, ' and status: ', result.data);
            if (result.data == "1"){
                var request = ".host" + respuesta.data.hosts[i_host].ip_host.split(".").slice(0,4).join("");
                $(request).css("border-top", "3px solid blue");
            }
    
            if (i_host === max_host-1) {
                console.log('COMPLETED Principal');
                i_host = 0;
                NProgress.done();
            } else {
                // NProgress.start();
                if (i_host < max_host-1){
                    NProgress.configure({parent: '.host' + respuesta.data.hosts[++i_host].ip_host.split(".").slice(0,4).join("")});
                    CheckPingAjax(i_host, callback);
                }
            }
        });
    }
      Votos: 1 - Link respuesta
     
Para participar activamente de la comunidad primero debes autenticarte, ingresa al sistema.Iniciar Sesión