I am trying to run two functions onLoad, one needs to run first so the second one can populate a boxlist, however, the second one doesn't get thearray

Viewed 73

I have two functions that I am trying to run when I load the page. dataRetrieve() gets the data from a firebase collection. populate() is supposed to populate a boxlist with the entries retrieved from dataRetrieve(). The main problem is that it lists the array as empty when I run populate() after dataRetrieve() no matter what I try. The last thing I tried was this:

            async function dataRetrieve(){
                const getAdmins = firebase.functions().httpsCallable('getAdmins');
                        // Passing params to data object in Cloud functinon
                getAdmins({}).then((results) => {
                    admins = results;
                    console.log("admins retrieved");
                    console.log(admins);
                }).then(() => {
                    populate();
                });
            }

async function populate(){

                let list = document.getElementById("user-list");

                //loop through users in out Users object and add them to the list
                for (var i = 0; i < admins.length; i++) {
                    let newItem = document.createElement('option');
                    newItem.innerHTML = admins[i].first + " " +admins[i].last;
                    newItem.id = admins[i].uid;
                    if (i == 0) {
                        newItem.className = "active";
                    }
                    console.log(newItem.innerHTML + "  " + newItem.id)
                    list.appendChild(newItem);
                }

                updateResponse(list.firstChild);

                list.size = admins.length;
                console.log(document.getElementById("user-list").size)
                //collect all the list items
                let listItems = list.querySelectorAll('option');

                //loop through the list itmes and add a click listener to each that toggles the 'active' state
                for (var i = 0; i < listItems.length; i ++) {
                listItems[i].addEventListener('click', function(e) {
                    if (!e.target.classList.contains('active')) {
                    for (var i = 0; i < listItems.length; i ++) {
                        listItems[i].classList.remove('active');
                    }
                    e.target.classList.add('active');
                    
                    updateResponse(e.target);
                    }
                })
                }
            }

also, admins is a global variable listed at the start of the script:

            var admins = [];

I am trying to run all this onload so I can instantly generate the list I thought that .next would cause it to wait to get the values before running, but even making results a parameter and transferring it directly into the function that way gives an undefined array. I don't understand why the function insists on calling on old data. Pls help.

2 Answers

I'm not sure what updateResponse function does. If it's not returning a promise then I'd make the populate function synchronous first. Also do you really need to use admins array somewhere else apart from populate function that it is a global variable? If not then I'd just pass it as a parameter.

async function dataRetrieve() {
  const getAdmins = firebase.functions().httpsCallable('getAdmins');
  // Passing params to data object in Cloud function
  const results = await getAdmins({})
  console.log("admins retrieved");
  console.log(results);
  // Passing results in populate function
  populate(results.data)
  // If your function returns an array, pass the array itself
}

function populate(admins) {
  let list = document.getElementById("user-list");

  //loop through users in out Users object and add them to the list
  // Using a for-of loop instead so no need to worry about checking the length here
  for (const admin of admins) {
    let newItem = document.createElement('option');
    newItem.innerHTML = admin.first + " " + admin.last;
    newItem.id = admin.uid;
    //if (i == 0) {
    //  newItem.className = "active";
    //}
    console.log(newItem.innerHTML + "  " + newItem.id)
    list.appendChild(newItem);          
  }

  updateResponse(list.firstChild);

  // rest of the logic
}

I guess you know how to check when the page loads. call the retrieve function when the page is loaded. Then you should call the populate function at the end of the retrieve function. this makes sure that the populate function is called after you get all the data

Related