Soy nuevo en javascript, así que lo siento si esto se ha preguntado antes.
Tengo esta función que uso para leer archivos json.
const jsonfile = require('jsonfile'); function readData(fileName: string, callback) { jsonfile.readFile(".\\data\\" + fileName + ".json", 'utf8', function (err, data) { if (err) console.error(err) callback(null, data); }) }Entonces lo llamo usando esto:
// Read JSON files var fileList = ["guides"]; var files = {}; for (let i = 0; i < fileList.length; i++) { readData(fileList[i], function (err, result) { if (err) throw err; files[i] = result; }) }pero cuando yo:
console.log(files['guides']); devuelve undefined . ¿Alguien puede ayudarme a arreglar esto? Muchísimas gracias.
La función de devolución de llamada de la función jsonfile.readFile se llama de forma asíncrona y su instrucción console.log se ejecuta de forma síncrona.
El código asincrónico se ejecuta después de que finaliza la ejecución sincrónica de su código javascript; como resultado, su instrucción console.log está registrando files['guides'] antes de que se agregue la propiedad de guides en el objeto de files . Por eso te quedas indefinido.
El siguiente ejemplo de código muestra este problema en acción:
let a = 1; setTimeout(() => { a = 2; }, 100); console.log(a); El fragmento de código anterior genera 1 porque la función de devolución de llamada de setTimeout se invoca de forma asíncrona , es decir, después de que se haya ejecutado la instrucción console.log(a) y en el momento de la ejecución de la instrucción console.log , el valor de a es 1 .
Solución
Para asegurarse de registrar files["guides"] después de que se hayan leído todos los archivos y se haya llenado el objeto de files , puede devolver una promesa de la función readData .
El siguiente código muestra cómo podría crear un contenedor de promesa alrededor de la función readData :
function readData(fileName) { return new Promise((resolve, reject) => { jsonfile.readFile(".\\data\\" + fileName + ".json", 'utf8', function (err, data) { if (err) reject(err); else resolve(data); }) } };Ahora puede llamar a la función anterior como:
Promise.all(fileList.map(filePath => readData(filePath))) .then(dataFromAllFiles => { console.log(dataFromAllFiles); }) .catch(error => console.log(error));Enlaces útiles: