0

Tengo una duda, posiblemente de novato, pero nunca me habia sucedido. Tengo una funcion, la cual realiza una consulta ajax y retorna un objeto, en esto no hay problemas, el ajax funciona y logro recibir el resultado y guardarlo en una variable:

function dataAjaxChart(fecha) {

    var datos = [];

    fechaAjax= new FormData();
    fechaAjax.append("fecha", fecha);

    $.ajax({
        type: "post",
        url: "fechas_grafico.php",
        data: fechaAjax,
        dataType: "json",
        cache: false,
        contentType: false,
        processData: false,
        success: function (response) {

            datos["fechas"] = response.data.fechas;
            datos["cantidades"] = response.data.cantidades;

        }
    })

    return datos;

}

El problema me surge al momento de almacenar lo retornado en una variable o realizando un console.log a la misma variable datos, ya que lo almacenado queda asi:

Array []
   fechas: Array (5).....
   cantidades: Array (5)....

El drama con ello, es que no puedo leer el array retornado, ya que trato de hacerlo con datos[0], datos["fechas"] o datos.fechas y no consigo nada. Si me pueden echar una mano, muy agradecido.

Actualizo con una foto la respuesta que obtengo: Respuesta Ajax

Si se fijan, al inicio, donde estan los primeros corchetes [] es donde inicia el array y muestra como si estuviese vacio y luego los demas elementos, y si yo hago un console.log a datos[0], muestra undefined.

Oriel
  • 281
  • 1
  • 11

1 Answers1

0

Para que te funcione el código que propones recuerda que una petición ajax no es sincrona, es asincrona, es decir, para darme a entender lo que digo es que cuando la función se encuentre con tu llamada a ajax, va a ejecutarla y mientras ajax de una respuesta la función seguira haciendo lo suyo, y que es lo que sigue en la función? exacto, el return statement que tienes, y si los datos de ajax no se han cargado antes de que hagas return es evidente lo que va a pasar, tu arreglo no tendra nada dentro.

Para solucionarlo tendras que promisificar tu llamada a ajax, talvez no entiendas que significa promisificar, pero en resumen es meter lo que quieras retornar dentro de una promise, donde una promise no es mas que una función que nos da dos callbacks y que se resuelve o rechaza en el tiempo.

Por ejemplo, promisifiquemos tu código:

function dataAjaxChart(fecha) {

    return new Promise((res, rej) =>{

        var datos = [];

        fechaAjax= new FormData();
        fechaAjax.append("fecha", fecha);

        $.ajax({
            type: "post",
            url: "fechas_grafico.php",
            data: fechaAjax,
            dataType: "json",
            cache: false,
            contentType: false,
            processData: false,
            success: function (response) {

                datos["fechas"] = response.data.fechas;
                datos["cantidades"] = response.data.cantidades;

                res(datos);
            },
            error: function(error){
                rej(error);
            }
        })

    });

}

dataAjaxChart(fecha).then(res =>{

    //Solo aquí dentro tus datos estaran disponibles
    datos = res;
    console.log(datos);

});

Si deseas mas información sobre las promises, hace poco respondí una pregunta que sin querer no tenia que ver del todo con aquello que se preguntaba, y en resumen termine explicando mas a fondo las promises, en los comentarios te la dejo.

Riven
  • 5,728
  • 2
  • 7
  • 27
  • Creo que no es necesario hacer una promesa, el problema que tiene es en el seteado de los datos. – Leo Castellanos Apr 24 '20 at 03:13
  • Uffff casí que no encuentro la pregunta, mas o menos por la mitad se explican las promesas un poco mas a fondo si estas interesado Oriel: https://es.stackoverflow.com/questions/346815/obtener-ruta-de-un-archivo-selecionado/347091#347091 – Riven Apr 24 '20 at 03:20
  • Ahi actualice y agregue una foto al final de la publicacion para que revisen y comprendan. Realice la promesa, pero yo necesito guardar en una variable que retorno fuera de la funcion, realizando la promesa sucede el mismo caso, primero muestra Array [] y al abrir el array, los demas elementos, pero no logro acceder a ellos. – Oriel Apr 24 '20 at 03:43
  • Amigo, ajax es asincrono y javascript es sincrono, y tu quieres que tu variable sea global, no puedes hacer eso simplemente, es decir, cualquier cosa que sea asincrona quedara atrapada en una promesa o solo podrá ser usada cuando eso que sea sincrono se haya terminado de ejecutar, simplemente no hay manera de hacer que ajax sea sincrono sin volver a quedar en otra promesa. no hay la solución que deseas por impedimentos de javascript. sin embargo dentro del then podras usar tu variable con sus valores sin ningun problema. – Riven Apr 24 '20 at 03:57
  • La solución a ello es solo usar los datos de esa variable cuando la promesa haya sido resuelta, por ejemplo hacer tus operaciones dentro del then o hacerlo al revez, es decir, dentro de la función que vayas a usar estos datos por ejemplo, usar el then de la promesa y dentro del then hacer las operaciones, ya otro gallo cantaria si lo que quieres no es usar esa variable globalmente y que se asigne sincronamente, por ejemplo si solo quieres usar esa variable dentro de otra función hay otra opcion pero fuera en el contexto global, no hay nada que hacer mas que usar tus datos dentro del then. – Riven Apr 24 '20 at 04:02
  • Este post clarifica mas lo que trato de decir respecto a ajax, las promises y la asincroneidad: https://es.stackoverflow.com/a/64403/98940 – Riven Apr 24 '20 at 05:19