0

A very small example

let value = null;
const getValues = () => {
  fetch('/third-party-api')
    .then(res => res.json())
    .then(data => {
      value = data;
    })
}

getValues();

app.get("/values", async (req, res) => {
  res.json(value);
});

When it is getting deployed, it will work. But after x-amount of time (sometimes hours, sometimes it will work the whole day), the value will get back to being null. I am paying for Heroku, so the server will never sleep, and this is why it doesn't make sense to me why this happens.

Can I somehow prevent this, so the value won't get back to being null?

Why I'm doing this:

The third-party API is huge and takes around 30 sec to fetch. So I simply create this tiny API to add pagination and only call the third party on build

jonask
  • 679
  • 2
  • 6
  • 21
  • Does this answer your question? [Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron) – evolutionxbox Jan 26 '22 at 08:15
  • I don't see the reason for this to not work. Try setting "value" as global variable, if possible. `global.value = null` – Rajan Jan 26 '22 at 08:18
  • The `get('/values'` function call does not wait for the value to exist. Please take a look at the question I've linked. – evolutionxbox Jan 26 '22 at 10:14
  • Hi @evolutionxbox - Thanks for reply. I am aware I an first able to call /values after getValues is done. Waiting 1-2 minutes after deploy is enough, here it works. The question is why it gets back to null – jonask Jan 26 '22 at 10:56
  • I suspect this example is simplified to the point where we're missing the actual problem. Do you call `getValues()` every time your app starts up? Heroku dynos restart frequently, at least once per day, and since this is just in memory you'd have to fetch the data again. – ChrisGPT was on strike Jan 26 '22 at 12:45
  • Hm okay. There is something I need to investigate with Heroku. I thought it wasn't restarting at all when you paid for it. Thanks – jonask Jan 26 '22 at 14:53
  • No, dynos don't _sleep_ if you pay for them. But [they restart pretty frequently](https://devcenter.heroku.com/articles/dynos#automatic-dyno-restarts). – ChrisGPT was on strike Jan 27 '22 at 02:44

1 Answers1

0

You can simply use middleware in your route if you use this method specifically in this route. You can do something like this:

let value = null;
const getValues = async (req, res, next) => {
  if (!value) { 
    next();
  }

  try {
  const res = await fetch('/third-party-api');
  const resJson = JSON.parse(res);
  value = resJson;
  next();
  } catch (e) {
     res.send({error: e});
  }
}

// getValues(); remove this call

app.get("/values", getValues ,async (req, res) => {
  res.json(value);
});
Apoorva Chikara
  • 8,277
  • 3
  • 20
  • 35
  • Wouldn't this execute getValues, every time I call /values? – jonask Jan 26 '22 at 08:21
  • It will be redundant to call "getValues" for every request, @jonask wants it only once for every build. – Rajan Jan 26 '22 at 08:22
  • Yes, I made the changes now, and if you don't have values for any reason, it will fetch first and then call the next middleware. And this is the beauty of middleware if there is some processing based in previous steps. I would recommend you to keep such data in states and fetch it from there or may be redis cache can be a good option. – Apoorva Chikara Jan 26 '22 at 08:23
  • @Rajan yes, but what if some other code that is not the part of the question sets the value to `null`? Does it solve the problem? No, it is similar to checking cache and return response based on value state. – Apoorva Chikara Jan 26 '22 at 08:26