기존 코드
function readJSONFiles() {
fs.readdir('./.lighthouseci', (err, files) => {
if (err) throw err;
else {
const jsonFiles = files.filter(file => file.startsWith('lhr-') && file.endsWith('.json'))
const arr: string[] = [];
jsonFiles.forEach(file => {
fs.readFile(`./.lighthouseci/${file}`, 'utf8', (err, data) => {
if (err) {
console.error(err)
} else {
arr.push('a')
return data
}
})
})
console.log(arr)
}
})
}
readFile내부에서 arr배열에 ‘a’를 담고 있다. jsonFiles에는 n개의 데이터가 담겨 있기에 fs.readFile은 n번 실행되지만, console.log(arr)를 실행하면 [] 빈배열이 출력 된다.
원인
fs.readFile()의 비동기성이 원인이었다.
fs.readFile()은 비동기식 I/O로 파일을 읽는다. 즉, 실행하고 있던 코드와 다른 흐름으로 실행이 된다는 말이다. fs.readFile()로 파일을 읽기 전에 console.log가 실행되어 빈 배열이 출력되는 것이다.- 그래서, 파일을 읽은 후 어떠한 행동을 취하고 싶다면 세 번째 인자 callback함수에서 실행하면 된다.
해결 방법
: fs.readFileSync 사용
fs.readFileSync()는 동기식 I/O로 파일을 읽는다. fs.readFile()과 달리 실행하고 있던 코드와 같은 흐름에서 실행되기에, 예측 가능하다는 장점이 있지만, 하던 작업들이 블로킹되기에, 성능 면에서 좋지 않다는 단점이 있다. 이번처럼 파일을 다 읽은 뒤에 결과를 바로 써야 하는 경우에는 이 쪽이 더 나았다.