Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NodeJS: TypeError: Cannot read property 'json' of undefined

I'm creating a CronJob that calls an API and store its response in the database:

const CronJob = require("cron").CronJob;
const btc_price_ticker = require("../../controllers/BtcExchange/Ticker");
const currency = require("../../controllers/Currencies/CurrenciesController");

module.exports = new CronJob("* * * * * *", async function() {
  const {
    ticker: { sell }
  } = await btc_price_ticker.getBtcPrice();
  currency
    .update({
      params: {
        id: "5cbdf078f5bcec257fcec792"
      },
      body: {
        exchange_rate: sell,
        lastUpdate: Date.now()
      }
    })
    .catch(error => console.log(error));
});

It works fine, however I receive a TypeError: Cannot read property 'json' of undefined

I'm using the same function to update the database I use when updating by my API:

module.exports = {
  async update(req, res) {
    const currency = await Currency.findByIdAndUpdate(req.params.id, req.body, {
      new: true
    });
    return res.json(currency);
  }
};

The TypeError happens in the return res.json(currency), and it only happens when it's called by the CronJob. When I put new information by API, it doesn't show any error.

I think it happens because when I call the function in CronJob, I just pass the req by parameter, but I don't know how to solve it. What am I supposed to do?

Thanks in advance!

like image 725
Otavio Bonder Avatar asked Apr 22 '19 17:04

Otavio Bonder


1 Answers

There's a famous saying which says that you can solve almost any problem in CS by adding another layer of indirection. This is one of those cases:

Instead of of declaring your module as:

module.exports = {
  async update(req, res) {
    const currency = await Currency.findByIdAndUpdate(req.params.id, req.body, {
      new: true
    });
    return res.json(currency);
  }
};

Separate the logic from the route-logic:

module.exports = {

  async getCurrency(id, params) {
      const currency = await Currency.findByIdAndUpdate(id, params, {
        new: true
      });
      return currency;
  }

  async update(req, res) {
    const currency = await getCurrency(req.params.id, req.body);
    return res.json(currency);
  }
};

Now the route can call update() and the cron-job can call getCurrency() directly.

like image 99
Nir Alfasi Avatar answered Oct 26 '22 00:10

Nir Alfasi