Global Array Variable Null


#1

So I am processing a forEach on an array coming in POST body. Within that loop I am calling a database API to get info on the item coming in to create an array of cards to be displayed. I can see all the items and then the call to the database API - it pushes the data into the card element. All looks good but once outside the forEach the array of cards is empty. I am sure it’s something dumb that I am missing. I do know that the #2 CONSOLE.LOG(‘2’) is displayed before the forEach runs and CONSOLE.LOG(‘1’) displays. So how to you get the forEach to run first them can display cards.elements. Appreciate any help. Here is the code:

   app.post('/items', (req, res) => {
       
     req.body.topItems.forEach((item)=>{
       
        var nameRequestUrl = req.body.name + '/items/' + item;
        var nameRequestHeaders = {
           'n-Access-Token': process.env.APP_TOKEN
        };
       
        request.get(nameRequestUrl, { headers: nameRequestHeaders })
          .then((result) => {
            var data = JSON.parse(result)
              cards.elements.push({ 
                  "title": data.item.title,
                  "image_url": data.item.image.src
              })

     console.log('1',cards.elements)
  
          })
       
         .catch((error) => {
              console.log(error)
              //res.status(error.statusCode).send(error.error.error_description);
          });
      });
  
     console.log('2',cards.elements)
  
  });

MOD EDIT: edited to clean up code formatting


#2

Hi @Jeff it looks to me like you’re running into a classic asynchronous programming problem; the reason your console.log(‘2’) code is executing before your console.log(‘1’) code is that the Node runtime reaches that part of your code before the promise returned by request.get() is fulfilled, and when Node executes console.log(‘2’) there’s nothing in the cards array.

One way to handle this is to chain then clauses for your promises since each then() itself returns a promise. So at a high level your code might look like:

request.get()
  .then( () => {
    //  do your database calls
  })
  .then( () => {
    //  do stuff with your cards array
  })
...

Depending on which promise library you’re using they each have some more detail in their documentation.

Hope this helps!


#3

@cori thanks! Yea that sounds like the issue where ‘2’ is displaying before ‘1’.

As far as the process - the request is fine. So here is a small ex.

forEach()
Request.get
.then( add to array)

This is all working fine - what I need to get is when the forEach is done then display the array. Right now the array is getting displayed before its filled. So do I need to get the index of the forEach and when on the last one added to the array display the array then?


#4

Ah yes, sorry I missed that wrinkle.

In that case you’ll probably want to wrap your forEach in a promise of its own that you can then handle when resolved, utilizing the now-filled cards array. The general Promise.all pattern might be a good place to start digging into that.


#5

A simpler way is to use async and await.

That would look something like this:

   app.post('/items', async (req, res) => {  <-- Added async here
   
    for (var i = 0; i < req.body.topItems.length; i++) { <-- forEach won't work well with await
      var item = req.body.topItems[i];
   
      var nameRequestUrl = req.body.name + '/items/' + item;
      var nameRequestHeaders = {
         'n-Access-Token': process.env.APP_TOKEN
      };
   
      var result = await request.get(nameRequestUrl,   <-- added await
             { headers: nameRequestHeaders });
      var data = JSON.parse(result)
      cards.elements.push({ 
          "title": data.item.title,
          "image_url": data.item.image.src
      })
  });

This won’t make the requests in parallel like it did before, but it’s a lot easier to work with. You can put a try/catch in there if you want to handle errors on the get request, too.


#6

Thanks I will take a look!


#7

Thanks i will give that a try!


#8

I just found this article that sums it up - the ideas you guys said!


#9

Thanks TIm!!! This was way easier and worked like a charm. I tried so many variations for this and kept getting ZERO card elements once done even though it was loading in the .THEN! I have the try/catch in there as well!!!