Pass data to view in express handlebar

Viewed 77

I'm struggling to get some data sent to my view page. I think it is to do with the order the code is running. This is my code;

exports.home = (req, res) => {
  let fileMessage = 'starting message';
  const fileSys = 'public/data/';
  const fileArray = [];
  fs.readdirSync(fileSys, (err, files) => {
    if (err) console.log(err);
    else {
      files.forEach((file) => {
        if (path.extname(file) === '.csv') {
          fileArray.push(file);
        }
      });
      if (fileArray.length === 1) {
        fileMessage = 'OK';
        console.log(fileMessage);
      }
      if (fileArray.length > 1) {
        fileMessage = 'loads';
        console.log(fileMessage);
      }
      if (fileArray.length === 0) {
        fileMessage = 'none';
        console.log(fileMessage);
      }
    }
  });
  console.log('before render');
  res.render('index', {
    title: 'Admin',
    fileMessage,
    home: true
  });
  console.log('after render');
};

In this format I get the following output;

before render
after render

Where clearly the file read is not happening.

If I change to readdir() i get;

before render
after render
none

So the file read function is occurring and getting the correct value however the value passed into the view template is still 'starting message'

I can't work out how to get this in the correct order so that i can pass the fileMessage variable to my view file with either, OK, loads, none

1 Answers

I have modified your code ,you are using readdirSync in wrong way. If you want to use Callbacks ,then use readdir only ,Also as the operation is async you are getting the initial value of fileMessage rendered in the browser (the data is being sent to the browser even before the file reading is done),So you should send the response back to browser in the callBack function like the way I did below.

exports.home = (req, res) => {
        let fileMessage = 'starting message';
        const fileSys = 'public/data/';
        const fileArray = [];
        fs.readdir(fileSys, (err, files) => {
          if (err) console.log(err);
          else {
              console.log(files);
            files.forEach((file) => {
              if (path.extname(file) === '.csv') {
                fileArray.push(file);
              }
            });
            if (fileArray.length === 1) {
              fileMessage = 'OK';
              console.log(fileMessage);
            }
            if (fileArray.length > 1) {
              fileMessage = 'loads';
              console.log(fileMessage);
            }
            if (fileArray.length === 0) {
              fileMessage = 'none';
              console.log(fileMessage);
            }
          }
          console.log('before render');
      res.send(fileMessage)
        console.log('after render');
        });
        
      }

And if you are planning to use readirSync

(Which I typically won't suggest doing because it will block the event loop)

Then the correct syntax would be

const fs = require('fs'); 
  
// Function to get current filenames 
// in directory 
filenames = fs.readdirSync("public/data);

Then you can iterate the fileNames Array.

Related