Check folder/file exist before read and write to the file. Nodejs

How can I check if the folder/file exist before read and write to the file? I did some search and it shows that using “fs.stat() or fs.access() to check if a folder/file exists” but I also read some related questions (related question one, related question two) and it appears to be that I might get some kind of “race condition”.

I am thinking of doing below approach to avoid “race condition”, am I still going to get some kind of “race condition” with below approach?:

const checkIfFolderOrFileExist = () => {
  return new Promise((resolve, reject) => {
    fs.access(filePath, constants.F_OK, (err) => {
      if (err) {
        reject(err);
      } else {
        resolve("exist");
      }
    });
  });
};

const createFolder = () => {
  return new Promise((resolve, reject) => {
    fs.mkdir(folderPath, { recursive: false }, (err) => {
      if (err) {
        reject(err);
      } else {
        resolve("done");
      }
    });
  });
};

const writeToTheFile = (data) => {
  return new Promise((resolve, reject) => {
    fs.writeFile(filePath, data, (err) => {
      if (err) {
        reject(err);
      } else {
        resolve("Done");
      }
    });
  });
};

const callBothPromiseFunction = async () => {
  /* Does below code has a possibility that I might get some kind of "race condition"? (I am using fs.access and fs.writeFile) */
  const folderOrFileExist = await checkIfFolderOrFileExist(); //<---- using fs.access
  if (folderOrFileExist === "exist") {
    const response = await writeToTheFile(someRandomData);
    /* some other js codes */
  } else {
    await createFolder();
    const response = await writeToTheFile(someRandomData);
    /* some other js codes */
  }
};

How about something more like:

const fs = require('fs');
const { writeFile, access, mkdir } = fs.promises;
const path = require('path');

const folderExists = async (filePath) => {
  try {
    await access(filePath, fs.constants.F_OK)
    return true
  }
  catch(err) {
    return false
  }
};

const createFolder = async (folderPath) => {
  await mkdir(folderPath, { recursive: false });
};

const writeToFile = async (filePath, data) => {
  const folderPath = path.dirname(filePath);
  const doesFolderExist = await folderExists(folderPath);
  if (!doesFolderExist) {
    await createFolder(folderPath);
  }
  await writeFile(filePath, data);
    /* some other js codes */
};
1 Like

But is there a way I can create my own promise rather than using “fs.promises” like my original examples? cause most of my codes are wrote that way and I would like to keep it consistent.

Why reinvent the wheel? You are already using fs, so why not take advantage of all of the package features? It simplifies your original code.

To answer your question, yes it can be done.

const fs = require('fs');
const path = require('path');

const folderExists = (filePath) => {
  return new Promise((resolve) => {
    fs.access(filePath, fs.constants.F_OK, (err) => {
      resolve(!err);
    });
  });
};

const createFolder = (folderPath) => {
  return new Promise((resolve, reject) => {
    fs.mkdir(folderPath, { recursive: false }, (err) => {
      if (err) {
        reject(err);
      } else {
        resolve("done");
      }
    });
  });
};

const writeToTheFile = (filePath, data) => {
  return new Promise((resolve, reject) => {
    fs.writeFile(filePath, data, (err) => {
      if (err) {
        reject(err);
      } else {
        resolve("Done");
      }
    });
  });
};

const writeToFile = async (filePath, data) => {
  const folderPath = path.dirname(filePath);
  const doesFolderExist = await folderExists(folderPath);         if (!doesFolderExist) {
    await createFolder(folderPath);
  }
  await writeToTheFile(filePath, data);
};
1 Like

Hi, thank you so much for helping me with the problem :+1: :+1: . I really appreciate it :fist_left:.

The reason I did the more complex way is because I am still learning about js, promise and async & await, so I feel that I should do more complex way, so that I can understand more how promise and async & await actually works. :smiley: :smiley:

Again, thank you so much for taking the time to help me with my problem. :+1:

Can you explain what the sequence of actions you’re intending here is? I’m just a bit confused. I realise you’re just figuring things out & the code reflects that, & the main aim is that you want to grok async. But I feel like this has elements of an XY problem (you’re asking about your solution rather than the problem).

So you want to create a file or a directory, unless either of those exists.

So how does the function you’re writing know what you’re trying to do? Why do you need both options covered in the same block of code? Because the logic you’ve written (and the fixes to that that have come in the replies) don’t really answer that question. I think it might be important