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.