1

I am new to the javascript/node.js event driven paradigm.

I need to stop the for after forEach to make sure all files have been read and then I continue. How should I implement wait_for_all_files_read() in this context?

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)

Neither solution [1] or [2] work for me.

2 Answers 2

4

I can suggest you to rewrite the code to promise - it will make much easy to deal with it

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))

Next step what you may do - move the code to async/await functions

UPD

Assume you need read only one file, then parse it data to json and analyze the result somehow.

It this case you can do next:

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)
})

Then assume you need to analyze bunch of files

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)
  })

Try to google some article to read how does promises work. E. g. you can start form mdn article

Sign up to request clarification or add additional context in comments.

5 Comments

can I use function(name) {...} instead of name => readFile(name)?
inside readFile I have another callback, does it wait for all the inner callbacks as well?
nope. Promisify function just wrap function that has been passed as parameter with promise.
but readFIle has a callback inside itself. How to consider that?
Also, where should I place if(err) throw err; and element.obj=JSON.parse(data);?
1

How I would do that:

  1. Promisify fs.readFile (by using, for example Bluebird)
  2. Mark the function as async
  3. Make a list of callbacks (my_list.map instead of forEach)
  4. "await Promise.all(myListOfCallbacks)"
  5. Next line after await will be executed after all the operations been finished

Something like that:

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();

13 Comments

but readFIle has a callback inside itself. How to consider that?
when it's promisified it returns promise. We can use promise .then (or await) instead of providing a callback as an argument.
So, where should I place if(err) throw err; and element.obj=JSON.parse(data);?
you can remove try/catch block, than the error will be thrown by the Promise.all. regarding the elements - you can do it in the loop AFTER the Promise.all
I became very confused.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.