-3

I'm getting a referenceError which I've been unable to figure out.

Any time I make a change to some code and upload it to the server, I refresh the page in the browser to see the changes - however 90% of the time I get a 502 Bad Gateway error on the first load of the index page - if I hit refresh, it loads fine without any errors.

The error in console is:

You have triggered an unhandledRejection, you may have forgotten to catch a Promise rejection:
ReferenceError: sugar is not defined                                                
at /var/www/nodeapp/routes/index.js:80:17                                     
at processTicksAndRejections (internal/process/task_queues.js:97:5)           
  • I've indicated the error is for 'sugar' but it could also be any of the other records (syrup, water, etc) - it seems random as to which one errors.

This is my code:

router.get('/', function(req, res, next) {
    
  var waterSearch = '?Network=water&_sort=Votes'
  var sugarSearch = '?Network=sugar&_sort=Votes'
  var syrupSearch = '?Network=syrup&_sort=Votes'
  var jellySearch = '?Network=jelly&_sort=Votes'
  var promotedSearch = '?Promoted=true&_sort=Votes'

  
  getRecords(waterSearch)
  .then( data => {
    return water = data
  })
  getRecords(sugarSearch)
  .then( data => {
    return sugar = data
  })
  getRecords(syrupSearch)
  .then ( data => {
    return syrup = data
  })
  getRecords(jellySearch)
  .then ( data => {
    return jelly = data
  })
  getRecords(promotedSearch)
  .then ( data => {
    return promo = data
  })
  .then( () => {
    res.render('index', {  
      title: 'index',
      addClass: 'homePage',
      waterData: water,
      sugarData: sugar,
      syrupData: syrup,
      jellyData: jelly,
      promoData: promo
    }) 
  })
  .catch(e => { console.log(e) }) 

});

The function it calls is:

function getRecords(searchString) {

    return new Promise((resolve, reject) => {

        var url = projectAPI + searchString

        fetch(url)
        .then(res => res.json())
        .then(json => { resolve (json) })
        .catch(e => { console.log(e) })

    })
}

The data is being fetched from a strapi postgres cms on the same server.

As I mentioned, the error only occurs the very first time the index page is loaded from a browser after the app starts. After the browser page is refreshed everything works as it should.

Incidentally, if I have two browsers open - chrome and firefox, both browsers give the same error on the first load of the page - each browser has to be refreshed independently to get the index page to load properly.

If anyone could shed any light on what I'm missing, it would be most appreciated. Thanks in advance.

HMS
  • 157
  • 1
  • 1
  • 6
  • 1
    You have no such variables `sugar`, `water`, etc – CertainPerformance Jul 05 '21 at 00:01
  • It appears that you're trying to use variables like `sugar`, `water`, etc.. BEFORE they have values so the first time you run your code, it doesn't work. On subsequent times, you end up using the previous values which aren't current, but the code doesn't fail. – jfriend00 Jul 05 '21 at 01:52

2 Answers2

2

Remember that JavaScript does not wait for a promise to be fulfilled before moving to the next line, the fact that you have the promise written down that way one after the other doesn't mean that they will be resolved in that exact order.

I believe in the initial load your browser runs the promises and tries to fetch from the backend, it's entirely possible the backend doesn't send a response in time, so the browser would have already executed the last promise before some of the others get a chance to resolve. At this point you are left with some undeclared variables which causes the referenceError (since these variables are declared when the promise resolves). On second load however your browser has most of these items in cache so fetching is much faster.

To fix that, ensure that all the promises are resolved before the last one which renders the page. You can use Promise.all.

Something like

Promise.all([getRecords(waterSearch), getRecords(sugarSearch), getRecords(syrupSearch), getRecords(jellySearch), getRecords(promotedSearch)])
  .then(results => {
    // 'results' is an array that contains the result of all the fulfilled promises ordered exactly how they were ordered in the promise.all array
    return (
      water = results[0],
      sugar = results[1],
      syrup = results[2],
      jelly = results[3],
      promo = results[4]
    )
  })
  .then(() => {
    res.render('index', {  
      title: 'index',
      addClass: 'homePage',
      waterData: water,
      sugarData: sugar,
      syrupData: syrup,
      jellyData: jelly,
      promoData: promo
    }) 
  })
  .catch(e => { console.log(e) }) 

PS: While it's possible to declare javascript variables without using var or let or const, it's not exactly good practice. See this post

Samuel Anyanwu
  • 295
  • 3
  • 12
  • This is great, thank you Samuel for your detailed reply. I thought I was chaining the promises (the getRecords functions), so I thought the last .then would wait for all the promises to resolve. I didn't know how Promise.all worked either - now it makes much more sense - thanks again, you are a star! – HMS Jul 05 '21 at 13:04
0

Have you tried putting a catch block for every get as you have in the last one? .catch(e => { console.log(e) })

As the error says: you may have forgotten to catch a Promise rejection