Soy nuevo en el paradigma impulsado por eventos javascript / node.js.

Necesito detener for after forEach para asegurarme de que se hayan leído todos los archivos y luego continúo. ¿Cómo debo implementar wait_for_all_files_read() en este contexto?

my_list.forEach(function(element) {
  fs.readFile(element.file_path, function(err, data)  {
    if(err) throw err;
    element.obj=JSON.parse(data);
  });
});
wait_for_all_files_read(); <-----------
analyze(my_list)

Ninguna solución [1] o [2] funciona para mí.

2
ar2015 22 feb. 2018 a las 11:48

2 respuestas

La mejor respuesta

Cómo haría eso:

  1. Promisify fs.readFile (usando, por ejemplo, Bluebird)
  2. Marque la función como asincrónica
  3. Haga una lista de devoluciones de llamada (my_list.map en lugar de forEach)
  4. "espera Promise.all (myListOfCallbacks)"
  5. La siguiente línea después de await se ejecutará una vez finalizadas todas las operaciones

Algo como eso:

const {promisisfy} = require('util')
const fs = require('fs')
const readFile = promisify(fs.readFile)

const fileNames = getFilenamesArray();

async function executeMe() {
  try {
    const arrayWithFilesContent = await Promise.all(
      fileNames.map(name => readFile(name))
    );
    return analyze(arrayWithFilesContent);
  }
  catch (err) {
    handleError(err)
  }
}

executeMe();
1
Alex 22 feb. 2018 a las 09:29

Puedo sugerirle que reescriba el código para prometer: será mucho más fácil lidiar con él

const {promisisfy} = require('util')
const fs = require('fs')
const readFile = promisify(fs.readFile)

const fileNames = getFilenamesSomehow() // <-- returns array with path, e.g. ["./package.json", "/etc/hosts", "/etc/passwd"]

Promise.all(fileNames.map(name => readFile(name)))
.then(arrayWithFilesContent => analyze(arrayWithFilesContent))
.catch(err => handleError(err))

Siguiente paso lo que puede hacer: mover el código a funciones asíncronas / en espera

UPD

Suponga que necesita leer solo un archivo, luego analice los datos a json y analice el resultado de alguna manera.

En este caso puedes hacer lo siguiente:

readFile(singleFileName)
.then(function (singleFileContent) {
   return JSON.parse(singleFileContent)
})
.then(function (singleFileContentInJson) {
   return analyze(singleFileContentInJson)
})
.catch(funciton (error) {
  //here you can process all errors from functions above: reading file error, JSON.parse error, analyze error...
  console.log(error)
})

Entonces suponga que necesita analizar un montón de archivos

const fileNames = [...] // array with file names
// this create an array of promises, each of them read one file and returns the file content in JSON
const promises = fileNames.map(function (singleFileName) {
    return readFile(singleFileName)
    .then(function (singleFileContent) {
       return JSON.parse(singleFileContent)
    })
})

// promise all resolves (calls callback in 'then') all of promises in array are resolved and pass to then callback array with result of each promise
Promise.all(promises)
  .then(function (arrayWithResults) {
    return analyze(arrayWithResults)
  })
  // catch callback calls if one of promises in array rejects with error from the promise - so you can handle e.g. read file error or json parsing error here
  .catch(function (error) {
    //here you can handle any error
    console.log(error)
  })

Intente buscar en Google algún artículo para leer cómo funcionan las promesas. P.ej. puede comenzar desde el artículo mdn

3
RidgeA 22 feb. 2018 a las 10:02