'Reading file only after function is done

I have a function doSmth that creates a file "data.json" by the end. (the file IS created by the end of running the script.) However, when I try to fs.readFileSync it using await and then, it says

Error: ENOENT: no such file or directory, open 'data.json'

here is my code

const doSmth = async() => {
    await zip.forEach(async(relativePath: any, file: any) => {
        const fs = require("fs");
        let fileExists = fs.existsSync('data.json');
        if (fileExists) {
            fs.readFileSync('data.json')
            console.log("file already exists")
            fs.writeFileSync("data.json", JSON.stringify(""))
        } else {
            console.log("file didnt exist")
            fs.writeFileSync("data.json", JSON.stringify(""))
        }
    })
}

await doSmth().then(async () => {
    const fs = require("fs");
    console.log("reached")
    fs.readFileSync("data.json")
})

how do I wait for the data.json file to be created before reading it

Edit: from the comments changed my code to this and works

const doSmth = async() => {
    await Promise.all(zip.forEach(async(relativePath: any, file: any) => {
        return new Promise(resolve => {
            const fs = require("fs");
            let fileExists = fs.existsSync('data.json');
            if (fileExists) {
               fs.readFileSync('data.json')
                console.log("file already exists")
               fs.writeFileSync("data.json", JSON.stringify(""))
               resolve()
            } else {
               console.log("file didnt exist")
               fs.writeFileSync("data.json", JSON.stringify(""))
               resolve()
            }
      })
    }))
}

but now I have an await inside and it causes the same data.file not found error

const doSmth = async() => {
    await Promise.all(zip.forEach(async(relativePath: any, file: any) => {
        return new Promise(async resolve => {
            const eachFile = await zip.file(file.name).async("string")
            const jsonObject = JSON.parse(eachFile)
            const fs = require("fs");
            let fileExists = fs.existsSync('data.json');
            if (fileExists) {
               fs.readFileSync('data.json')
                console.log("file already exists")
               fs.writeFileSync("data.json", JSON.stringify(""))
               resolve()
            } else {
               console.log("file didnt exist")
               fs.writeFileSync("data.json", JSON.stringify(""))
               resolve()
            }
      })
    }))
}


Solution 1:[1]

the problem is you are not writing the file synchronously in your catch block

const doSmth = async() => {
    await zip.forEach(async(relativePath: any, file: any) => {
        const fs = require("fs");
        try {
            fs.readFileSync('data.json')
            console.log("file already exists")
            fs.writeFileSync("data.json", JSON.stringify(""))
        } catch (error) {
            console.log("file didnt exist")
            fs.writeFileSync('data.json', JSON.stringify(""));
            // Yes, writeFileSync does create a new file when the file is not exists
            // So even this catch is redundant, use fs.existsSync if you really need to know the file exists or not
        }
    })
}

or you might want to do a proper primisify for every thing

Solution 2:[2]

You are using await, but you are not returning promises.

We will use Promise.all to wait for all promises, and for each zip file, we return a new Promise when it's done by calling resolve()

const doSmth = async() => {
    await Promise.all(zip.map(async(relativePath: any, file: any) => {
        return new Promise(resolve => {
            const fs = require("fs");
            let fileExists = fs.existsSync('data.json');
            if (fileExists) {
               fs.readFileSync('data.json')
                console.log("file already exists")
               fs.writeFileSync("data.json", JSON.stringify(""))
               resolve()
        } else {
            console.log("file didnt exist")
            fs.writeFileSync("data.json", JSON.stringify(""))
            resolve()
        }
      })
    }))
}

PS: I did not count the close brackets, please edit it accordingly.

PS2: your data.json should be empty since you are using JSON.stringify("") which is a empty string

if you want to do things sequentially

import fs from 'fs';
const fsPromises = fs.promises;

const doSmth = async () => {
     return new Promise(async resolve => {
           for (let i = 0; i < zip.length; i++) { 
               const file = zip[i];
               if (await fsPromises.exists(file)) {  
                  await fsPromises.writeFile('data.json', file);
               } 
           }
           resolve(); //End the function by returning a promise.

     })


}

Solution 3:[3]

Don't mix and match async/await with then. It looks like you want to do somthing like this.

const fs = require('fs');

async function main() {
  await doSmth();
  console.log('reached');
  fs.readFileSync('data.json');
}

main();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 0nepeop1e
Solution 2
Solution 3 Andy