最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - NodeJS: TypeError: Cannot read property 'json' of undefined - Stack Overflow

programmeradmin4浏览0评论

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!

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!

Share Improve this question asked Apr 22, 2019 at 17:48 Otavio BonderOtavio Bonder 1,9995 gold badges22 silver badges38 bronze badges 7
  • do you have express using bodyparser – Len Joseph Commented Apr 22, 2019 at 17:49
  • You're calling update() without passing the response object as the second argument – Nir Alfasi Commented Apr 22, 2019 at 17:51
  • Yes @alfasin, you are right. I'm pretty sure this is the error, but I don't know what should I pass as the response object – Otavio Bonder Commented Apr 22, 2019 at 17:52
  • @OtavioBonder Ideally you should simply call Currency.findByIdAndUpdate or any other mon util function in the Corn rather than mocking req and res – priyansh gupta Commented Apr 22, 2019 at 18:04
  • If you're using cron-job, why do you need req/res from the first place? – Nir Alfasi Commented Apr 22, 2019 at 18:21
 |  Show 2 more ments

3 Answers 3

Reset to default 3

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.

Ok, maybe my approach isn't the best, but since I'm passing an undefined object to update(), and I don't need the response, I edited the update function:

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

So, since res is undefined, it doesn't return anything.

It's because both req and res is undefined (or atleast not the proper request and response object) when the route is not requested by client (which is the case here).

Simplest solution I can think of is mock (or make an actual call) a client call in your cron job by using modules like axios, request, request-promise (with Promise wrapper on top of request) like:

const rp = require('request-promise')

module.exports = new CronJob("* * * * * *", async function() {
  try {
    const {
      ticker: { sell }
    } = await btc_price_ticker.getBtcPrice();
    // assuming your server is running in localhost, port 3000 and route is 'myapi/:id'
    const url = "http://localhost:3000/myapi/5cbdf078f5bcec257fcec792";
    const options = {
      method: 'GET',
      uri : url,
      json: true,
      body: {
        exchange_rate: sell,
        lastUpdate: Date.now()
      }
    }
    const response = await rp(url);
  } catch(error) {
    console.log(error);
  }
});

Since you can execute the db methods, a simpler alternative would be to directly execute Currency.findByIdAndUpdate in your cron job. I don't see any reason why you would want to call your route in your code.

发布评论

评论列表(0)

  1. 暂无评论