1

I am trying to get this code below run as middleware from an exported function.

fs.stat("./tmp/my_data.json", (err, stats) => {
scraperDate = stats.mtime.toUTCString();
});

I have

let scraperDate = "";

in top of my routes file. Im trying to do this:

router.get("/", myFunctions.scraperDateFunction, function (req, res) {
res.render("my_view", {scraped: scraped, scraperDate: scraperDate});
});

When I just run the scraperDate code as it is, above the route, it works. When I put it in my functions.js file to module.exports it wont write to the scraperDate variable.

I am probably missing something obvious here, but I have tried to get this to work for the better part of two days now. This is my module.exports for the function:

module.exports = {
    scraperDateFunction: function(){
        fs.stat("./tmp/my_data.json", (err, stats) => {
            scraperDate = stats.mtime.toUTCString();
        });
    }
}

* Edit *

I have now tried this

getScrapeDate: function(req, res, next){
    fs.stat("./tmp/my_data.json", (err, stats) => {
        scraperDate = stats.mtime.toUTCString();
        console.log(err)
        console.log(stats)  
        return next;        
    });
}

which prints the stats as expected to console withour any errors. It is likely something with the scope. How would I pass the result of stats.mtime.toUTCString(); to the scraperDate variable in the route?

* Edit 2 *

I now have this in my functions file

    getScrapeDate: function(req, res, next){
    fs.stat("./tmp/my_data.json", (err, stats) => {
        if (err) {
            next (err);
        } else {
            res.locals.scraperDate = stats.mtime.toUTCString()
        }

    });
}

and this in my routes file as suggested but it does not load my view

router.get("/", myFunctions.getScrapeDate, function (req, res) {
    let {scraperDate} = res.locals;
    res.render("my_view", {scraped: scraped, scraperDate: 
    scraperDate});
});

scraped is declared in the top of the routes file.

* Final Edit *

This is a setup that is now working

router.get("/", myFunctions.getScrapeDate, function (req, res) {
    let {scraperDate} = res.locals;
    res.render("my_view", {scraped, scraperDate});
 });

and

    getScrapeDate: function(req, res, next){
    fs.stat("./tmp/my_data.json", (err, stats) => {
        if (err) {
            next (err);
        } else {
            res.locals.scraperDate = stats.mtime.toUTCString();
            next();
        }                   
    });
}
75martin
  • 105
  • 9

2 Answers2

0

The scraperDate variable inside the scraperDateFunction in your module is not exported, since scopes are not shared between different modules. This would break the entire purpose of modules.

Check the reference docs.

Javier Silva Ortíz
  • 2,864
  • 1
  • 12
  • 21
  • yes, Patrick Evans mentioned this. how do I access the stats part of the function? – 75martin Nov 26 '19 at 22:45
  • fs.stat("./tmp/my_data.json", (err, stats) => { return stats.mtime.toUTCString(); }); – Jesper Ordrup Nov 26 '19 at 22:50
  • 1
    tried fs.stat("./tmp/my_data.json", (err, stats) => { return stats.mtime.toUTCString()}); but it does not seem to pass on the date... – 75martin Nov 26 '19 at 23:02
  • @PatrickRoberts im dabbling with it right now... i recall using res.locals at some other place, thanks for the suggestion! ill update – 75martin Nov 26 '19 at 23:10
  • @75martin This is what the `res.locals` object is for. Setting variables directly on the request object is not supported or documented. `res.locals` is guaranteed to hold state over the life of a request. – Javier Silva Ortíz Nov 26 '19 at 23:12
  • @JavierSilvaOrtíz yes, I don't know why someone downvoted his first response.. :D – 75martin Nov 26 '19 at 23:16
0

Do not define scraperDate at the top of your functions module, and do not attempt to import it into your routes module either. At best this is code-smell, and at worst you end up inadvertently leaking information between separate request-response cycles that should not be shared.

What you should do is follow this recommendation to pass data between middleware using res.locals:

In your routes file:

router.get('/', myFunctions.scraperDateFunction, (req, res) => {
  const { scraperDate } = res.locals;
  // the following is shorthand in ES2015 syntax for
  // { scraped: scraped, scraperDate: scraperDate }
  res.render('my_view', { scraped, scraperDate });
});

And in your functions file:

module.exports = {
  scraperDateFunction (req, res, next) {
    fs.stat('./tmp/my_data.json', (err, stats) => {
      if (err) {
        next(err);
      } else {
        res.locals.scraperDate = stats.mtime.toUTCString();
        next();
      }
    });
  }
}

Again, do not try to define and export a top-level scraperDate variable in your functions file, this is a cleaner approach to passing data between your middleware in express.

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153