0

I have a .txt file that I want to save in a JS array and then console.log that array. I know from this answer how to read the file into an array, but the problem is when I try to console.log the array, it logs it as empty. Here's my code:

const fs = require('fs')
let arr = []
let fileReader = async () => {
  await fs.readFile('temp.txt', (err, data) => { 
    if (err) throw err; 
    console.log(data.toString()); // confirming that line is successfully read
    arr.push(data.toString());
  })
  console.log(arr)
}
fileReader()

I figured that the console.log would wait until the array had finished being populated in fs.readFile(), and so it would print the populated array. Note that I console.log every line when it's read, in order to confirm that text is indeed being pushed to the array.

Does anyone know why this approach wouldn't work, or how I can do it differently? I want to stick with the asynchronous readFile rather than the synchronous readFileSync for now. Note that if I did want to do it synchronously, this code works:

const fs = require('fs')
let arr = fs.readFileSync("temp.txt").toString('utf-8').split("\n")
console.log(arr)
gkeenley
  • 2,920
  • 1
  • 18
  • 45
  • That's a fairly broad question. Have you done any debugging to see where it's failing? You might use breakpoints rather than console logs to eliminate timing ambiguity. – isherwood Dec 01 '20 at 20:01
  • @isherwood I did use breakpoints to confirm that lines of text were being successfully read and pushed to the array. I also console.logged each line as it was being read. I've updated the original question to show this. Thanks for pointing this out. – gkeenley Dec 01 '20 at 20:08
  • 2
    `fs.readFile` returns immediately. the asynchronous logic is provided by passing a callback, so the `console.log(arr)` line should be place inside the callback itself. An alternative would be turning the `readFile` function into a real `async` function, for example promisifying it. – Marco Luzzara Dec 01 '20 at 20:15
  • @MarcoLuzzara Understood. Do you want to make this a reply so I can accept it? – gkeenley Dec 01 '20 at 21:33
  • @gkeenley don't worry, it's ok. If you need further explanation I can write an answer, otherwise "accept" the comment :) – Marco Luzzara Dec 01 '20 at 21:43
  • @MarcoLuzzara Ok so my understanding is that fs.readFile() returns immediately, ie BEFORE its callback has finished executing. So even though I `await` it, it returns and `console.log(arr)` runs before the callback has populated the array. Is that correct? – gkeenley Dec 01 '20 at 21:54
  • 1
    Exactly. Just an advice: always make sure that the awaited method actually returns a `Promise`. if it does not, the `await` operator is useless and it is better to omit it, to avoid confusing people who read your code. A simple rule of thumb is: callback and Promises do not usually get along, but if the async/await version with `Promise` is available, then go for it. – Marco Luzzara Dec 01 '20 at 22:27

1 Answers1

-1

Once you have your file data after data.toString() you can split it by \n. For example:


let data = data.toString()
let data_rows_arr = data.split('\n') //defines a new line seperator.

for(row of data_rows_arr){
   //Do something with your rows
}

Hope that helped you :)

Nir Gofman
  • 144
  • 1
  • 11