> Faqs > Como acceder a los datos de un array "cargado de datos" por fetch

Como acceder a los datos de un array "cargado de datos" por fetch

Hola, practico con unos ejercicios de javascript y tengo una duda.

El ejercicio es de lectura de un archivo en formato JSON. Hago la lectura usando fetch y guardo los datos adquiridos en un array.

El problema es que cuando accedo a la informacion en el array fuera del scope de fecth la consola de desarrolo del navegador (chrome y firefox) me dice que el array está undefined.

pero si escribo el nombre del array en la consola, si que me muestra la información pero no cuando trato de acceder al array desde el codigo (app.js) me dice que el array esta undefined.

Estoy haciendo algo mal y no se lo que es.

¿Alguna idea?

"use strict"

// Read JSON data from a file

let myArr = [];

async function readFile() {
    try {
        await fetch('http://localhost:8000/empleados.json')
            .then(data => data.json())
            .then(data => data.empleados.empleado.forEach(element => { 
                myArr.push(element);
            }));
        } 
        catch (error) { console.log(error);  }
}

readFile();

console.log(myArr);
console.log(myArr[0]);
console.log(myArr[1].nombre);

Respuestas

Hola Q tal!!

El problema que está ocurriendo se debe a la naturaleza asincrónica de la función fetch. Cuando llamas a readFile() y haces console.log(myArr) inmediatamente después, en la siguiente línea, el navegador intenta ejecutar el console.log antes de que la operación fetch haya terminado de completar su trabajo y de haber llenado myArr.

Dado que fetch es asincrónico, debes esperar a que la promesa se resuelva antes de intentar acceder a los datos. Una forma de asegurarte de que el array esté lleno antes de utilizarlo es hacer uso de await para esperar a que la función readFile termine.

Prueba con este otro código que hará que los datos estén disponibles cuando los uses:

"use strict"

// Read JSON data from a file

let myArr = [];

async function readFile() {
    try {
        const response = await fetch('http://localhost:8000/empleados.json');
        const data = await response.json();
        data.empleados.empleado.forEach(element => { 
            myArr.push(element);
        });
        // Aquí ya puedes acceder a myArr de forma segura
        console.log("Inside async function:", myArr);
        console.log("First employee:", myArr[0]);
        console.log("First employee name:", myArr[0].nombre);
    } catch (error) { 
        console.log(error); 
    }
}

readFile();

// Aquí, la función asíncrona aún no ha terminado cuando se ejecuta este console.log
console.log("Outside async function:", myArr); // Este se ejecuta antes de que se llene el array

El código se ha modificado para que los datos se procesen y se impriman dentro del mismo bloque donde se han obtenido, garantizando que el array esté lleno.

Si necesitas acceder a myArr fuera de readFile, tendrás que esperar a que la función haya terminado de ejecutarse. Esto lo puedes hacer de diversos modos, según tus necesidades o preferencias.

1. Uso de async/await en la llamada

Puedes hacer que la función que llama a readFile espere a que se complete antes de acceder a myArr. Para conseguir esto necesitas crear otra función asíncrona.

"use strict"

// Read JSON data from a file

let myArr = [];

async function readFile() {
    try {
        const response = await fetch('http://localhost:8000/empleados.json');
        const data = await response.json();
        data.empleados.empleado.forEach(element => { 
            myArr.push(element);
        });
    } catch (error) { 
        console.log(error); 
    }
}

// Función asíncrona para esperar la lectura del archivo
async function run() {
    await readFile();  // Espera que readFile() termine
    console.log("Array after readFile:", myArr); // Ahora myArr tiene los datos
    console.log("First employee name:", myArr[0].nombre);
}

run();

En el caso que acabamos de ver, la función run espera a que readFile termine (await readFile()), y solo después de que la promesa de readFile se resuelva, se ejecutan los console.log.

2. Uso de Promesas

Si te lian los async/await, puedes usar directamente las promesas de la siguiente forma:

"use strict"

// Read JSON data from a file

let myArr = [];

function readFile() {
    return fetch('http://localhost:8000/empleados.json')
        .then(response => response.json())
        .then(data => {
            data.empleados.empleado.forEach(element => {
                myArr.push(element);
            });
        })
        .catch(error => console.log(error));
}

// Llamada a la función readFile y luego acceso a los datos
readFile().then(() => {
    console.log("Array after readFile:", myArr); // Ahora myArr tiene los datos
    console.log("First employee name:", myArr[0].nombre);
});

En este caso, cuando readFile() resuelve la promesa, el código dentro de .then() se ejecuta, garantizando que myArr ya contiene los datos necesarios.

3. Enviar el retorno del array con readfile en vez de usar una variable global

Otro enfoque que podrías pensar es modificar tu función readfile para que devuelva los datos y los procese directamente donde los necesites. A mi me parece más lógico que usar una variable de array como global. Es más comprensible y evitas problemas de interferencias con elementos que no son de la función.

Igualmente necesitarás promesas o bien async await para usar esa función asíncrona y esperarte a que el array esté listo para luego usarlo.

"use strict"

// Read JSON data from a file

async function readFile() {
    try {
        const response = await fetch('http://localhost:8000/empleados.json');
        const data = await response.json();
        return data.empleados.empleado;
    } catch (error) { 
        console.log(error); 
    }
}

// Llamada a la función
async function run() {
    let myArr = await readFile();  // Espera los datos de readFile()
    console.log("Array after readFile:", myArr); // Aquí los datos ya están disponibles
    console.log("First employee name:", myArr[0].nombre);
}

run();

Espero que lo puedas ver claro. Cualquier cosa puedes hacer otra pregunta.

Victor
302 8 21 17
Uau... Respuesta super completa con distintos enfoques. Gracias mil Víctor

Prueba con

.then(response => response.json())
.then(data => {
    data.forEach(function(reg) {
        console.log(reg.<<campo>>);
        ...
        ...
    })
Enrique
0