Search code examples
javascripthtmlfirebaseasync-awaitcallable

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


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.


Solution

  • 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
    }