0

Every day i m learning new things in javascript(nodejs) however one thing that's quite confusing for me is the concept of async-await.

Need a little help in managing the sequence of execution in below code. here's how it should execute I m writing a daily script which should read file value from local system ( file contains : last run date). put a new value in the file after it finishes reading the file(File should store current date).

fs = require('fs');
path = require('path');
let todaysDate = new Date();

async function checkPreviousRunDate() {
  console.log("Step 1 : Today's Date: " + todaysDate.getDate());

  filePath = path.join(__dirname, 'lastrundetail.txt');
  var filedata;
  await fs.readFile(filePath, {
    encoding: 'utf-8'
  }, function(err, data) {
    if (!err) {
      console.log('Step 2 :Last run was done on(MM/DD/YYYY): ' + data);
      let lastrunDate = new Date(data);
      const diffTime = Math.abs(todaysDate - lastrunDate);
      const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
      console.log("Step 3 :Its been " + diffDays + " day(s) Since the last run");
      return data;
    } else {
      console.log(err);
      return "";
    }
  });

}

async function storeTodaysDateinLastRunFile() {
  console.log("Step 4 : Finally Saving the todays date in last run file: ");
  await fs.writeFile("lastrundetail.txt", todaysDate, function(err) {
    if (err) return console.log(err);
    console.log('Step 5 : Saved the record in file');
  });
  return todaysDate;
}

const main = async () => {
  let lastrunDate = await checkPreviousRunDate();
  let storedDate = await storeTodaysDateinLastRunFile();
}
main();

Output :

Step 1 : Today's Date: 4
Step 4 : Finally Saving the todays date in last run file:
Step 5 : Saved the record in file
Step 2 :Last run was done on(MM/DD/YYYY): Fri Dec 04 2020 13:10:01 GMT+0530 (India Standard Time)
Step 3 :Its been 1 day(s) Since the last run

Expected Output :

Step 1 : Today's Date: 4
Step 2 :Last run was done on(MM/DD/YYYY): Fri Dec 04 2020 13:06:26 GMT+0530 (India Standard Time)
Step 3 :Its been 1 day(s) Since the last run
Step 4 : Finally Saving the todays date in last run file:
Step 5 : Saved the record in file
VLAZ
  • 26,331
  • 9
  • 49
  • 67
linuxgenie
  • 77
  • 1
  • 8
  • `fs.readFile` doesn't return a Promise, so, you can't `await` it - same goes for `fs.writeFile` – Bravo Dec 04 '20 at 08:18
  • 2
    You should probably be using [the promise API for FS](https://nodejs.org/dist/latest-v10.x/docs/api/fs.html#fs_fspromises_readfile_path_options) rather than the callback one. `await fs.readFile` doesn't really wait for the whole reading of file to finish. – VLAZ Dec 04 '20 at 08:18
  • Does this answer your question? [fs.writeFile in a promise, asynchronous-synchronous stuff](https://stackoverflow.com/questions/31978347/fs-writefile-in-a-promise-asynchronous-synchronous-stuff) – tevemadar Dec 04 '20 at 08:27

1 Answers1

1

await is only useful on promises.

However fs.readFile returns undefined and therefore it does not make any sense to use it on it.

enter image description here

If you use VSC you can hover over and see that it returns void which means nothing which means undefined

What you can do is to promisfy readFile and writeFile. For this you can use new Promise()

function write(date) {
  return new Promise((res, rej) => {
    fs.writeFile("lastrundetail.txt", date, function(err) {
      if (err) return rej(err);
      res("Step 5 : Saved the record in file");
    });
  });
}

This function will return you an promise. You can either resolve with res or reject with rej

enter image description here

Now you can see it returns an promise

On error you reject otherwise you resolve the promise.

Same for readFile

function read(filePath) {
  return new Promise((res, rej) => {
    fs.readFile(
      filePath,
      {
        encoding: "utf-8"
      },
      function(err, data) {
        if (!err) {
          console.log("Step 2 :Last run was done on(MM/DD/YYYY): " + data);
          let lastrunDate = new Date(data);
          const diffTime = Math.abs(todaysDate - lastrunDate);
          const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
          console.log(
            "Step 3 :Its been " + diffDays + " day(s) Since the last run"
          );
          res(data);
        } else {
          rej(err);
        }
      }
    );
  });
}

Here i resolve the data. Later when we use let data = await read(...) it will return us our data. Now both functions returning an pending promise.

Now it makes sense to use await on our functions

async function checkPreviousRunDate() {
  console.log("Step 1 : Today's Date: " + todaysDate.getDate());
  filePath = path.join(__dirname, "lastrundetail.txt");
  let data = await read(filePath);
  console.log(data);
}

async function storeTodaysDateinLastRunFile() {
  console.log("Step 4 : Finally Saving the todays date in last run file: ");
  await write(todaysDate);
  return todaysDate;
}

In case some error occure you can wrap it in an try / catch which you usually should do. This will catch the rej error

async function checkPreviousRunDate() {
  console.log("Step 1 : Today's Date: " + todaysDate.getDate());

  filePath = path.join(__dirname, "lastrundetail.txt");
  try {
     let data = await read(filePath);
     console.log(data);
  catch (err) {
     console.log(err);
  }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
bill.gates
  • 14,145
  • 3
  • 19
  • 47