Unable to save Firebase snapshot data into an array using a promise

Although there are numerous resources on Javascript promises for loading Firebase objects, I have struggled to store the data in an array.

The challenge: Despite setting up an array (productArray below) to receive values from a Firebase snapshot, the array remains empty after exiting the forEach loop.

database.js:

  getProductList = function(){

    let productArray =[];

    loadFBData = function(){
      firebase.initializeApp(config);
      return firebase.database().ref().once("value", function(snapshot){
        return snapshot.val();
    });
  }

  Promise.all([loadFBData()]).then(function(snapshot) {
    snapshot.forEach(function(product) {
      productArray.push(product.val());
    });
  });
}

Question: I suspect I am mishandling Promise.all, but I cannot figure out how (since I am new to asynchronous functions). Any guidance on successfully populating productArray would be greatly appreciated.

Edit: Further explanation - it appears that snapshot contains the correct Firebase data and the forEach loop iterates through each item in snapshot properly. However, productArray remains empty outside of the Promise.all block.

Update: I have tried implementing all the suggestions provided so far, yet the program does not pause long enough to build an array from the snapshot object. In the past, I have used Angularfire's $loaded function, which effectively delayed the program execution. It is perplexing why a standard JS promise does not work here. Should I consider using setTimeout? Even attempting to combine alexmac's and Pointy's recommendations did not yield results:

 getProductList = function(){

    let productArray =[];

    loadFBData = function(){
      firebase.initializeApp(config);

      return new Promise(resolve => {
         firebase.database().ref().once('value')
            .then(function(snapshot){
               return resolve(function(snapshot){
                  productArray = Object.keys(snapshot).map((key, prod) => prod);
               });
            });
         });
   }

  loadFBData();
}

Answer №1

Insight

Your grasp on promises and the Firebase SDK seems to be a bit lacking.

To clarify, Firebase SDK functions return promises by default, eliminating the need for manually creating them. Additionally, Promise.all is used for combining multiple promises, while a single promise can be easily extended with .then().

If you're interested, I have a video tutorial on saving and querying data available here: Watch "Save and Query Firebase Data"

Furthermore, if you want to learn more about promises, feel free to watch my other video on the topic: Promises Video

Initializing Firebase

Remember to initialize firebase at the beginning of your page to avoid redundant initializations within functions.

You can simply call firebase.initializeApp(config) after loading the Firebase SDK or reference Firebase Hosting's init.js.

Illustration

The following example demonstrates loading the Firebase SDK, initializing firebase with my testing db's init.js, and performing queries and manipulations on an array.

Keep in mind that Firebase treats data as unsorted objects, not zero-indexed arrays. The example showcases different methods of handling and returning this data :)

<html>
  <head>
    <script src="https://www.gstatic.com/firebasejs/4.3.0/firebase.js"></script>
    <script src="https://quiver-two.firebaseapp.com/__/firebase/init.js"></script>    
    <script>
      function loadFirebaseArray(path) {
        return firebase.database().ref(path).once('value').then(snap => snap.val());
      }

      function toArray(items) {
        return Object.keys(items).reduce((array, key) => {
          const value = items[key];
          array.push({key, value});
          return array;
        }, []).sort();
      }

      loadFirebaseArray('stackoverflow').then(items => {
        console.log('items', items);

        const asArray = toArray(items);
        alert(JSON.stringify(asArray));

        const justTheValues = asArray.map(x => x.value).sort();
        alert(justTheValues);
      });
    </script>
  </head>

</html>

Answer №2

An example in action could resemble the following:

retrieveProductList = () => {
  let fetchFirebaseData = () => {
    firebase.initializeApp(config);
    return new Promise(resolve => {
      firebase.database().ref().once('value', resolve);
    });
  }

  let productList = [];
  fetchFirebaseData()
    .then(snapshot => {
      productList = Object.keys(snapshot).map((key, product) => product);
}

In this scenario, I utilize promisification to produce a promise for the firebase query. Therefore, as fetchFirebaseData yields a promise, it enables me to establish a promise sequence or employ ES7 async/await feature for awaiting completion before utilizing the outcome.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Differentiating the angular distinction between setting a variable with ng-click and invoking a function

I've encountered a situation like this before. Let's assume the controller has these variables: $scope.valueArr = ['Hello', 'No', 'Yes']; $scope.myValue = 'Hello'; And there is an ng-repeat as follows: ...

Fundamentals of Angular 2

It's not just an inconvenience, but something that truly frustrates me. Could someone please clarify the following: Why does Angular load these scripts in HTML directly from node_modules https://i.sstatic.net/D8UrG.png Why am I unable to simply imp ...

Troubleshooting Issue with Angular's ng-view Implementation

I have been following a tutorial on setting up a MEAN stack single-page application with the URL provided. However, after setting up the application, the views are not displaying in the ng-view div as expected. Here is the structure of my app: - app ---- ...

How can a method be called from a sibling component in Angular when it is bound through the <router-outlet>?

In my current project, I have implemented an application that utilizes HTTP calls to retrieve data from an API endpoint and then displays it on the screen. This app serves as a basic ToDo list where users can add items, view all items, delete items, and pe ...

Having trouble with WordPress jQuery Click function. Would greatly appreciate some assistance :)

There seems to be a mix of working and non-working jQuery code. Specifically, the click function is not functioning properly in this case. Here is an example of the code that works: $j=jQuery.noConflict(); // Using jQuery with $j(...) $j(document ...

Python web application encountering issues running in browser

After successfully creating a Python desktop application with Tkinter library, we decided to convert it into a web app using pyjamas. The conversion process generated html files and javascripts as expected. However, when attempting to open the html file i ...

What is the best way to dynamically update cells within an HTML table row when a single column is changed?

My webpage features an HTML table that is dynamically constructed. Within this table, I have made some of the cells editable, with one cell containing a calculated value based on two other cells in the same row. Here is a snippet of my table: <tr class ...

Suggestions for breaking out of the function update()?

Having some trouble escaping my update() function. Here's the attempt I've made: if (score.l1 > 20) { break; } However, all I get is an error message saying "Illegal break statement" ...

Incorporate a horizontal scrollbar feature within an HTML section

Currently, I am in the process of learning vue js and would like to create a layout that includes two sections. The first section should occupy 3 grids on the screen, be fixed, and not scrollable, with a division into 4 vertical parts. The second section s ...

How can we create a reusable dropdown list that appears when clicking on different elements?

Imagine having different sections of a webpage that, when clicked, reveal a dropdown list right below the selected link. I've noticed some websites accomplish this by actually having just one dropdown list defined in the DOM, which then appears below ...

What's the best way to save data from an HTML input field into a JavaScript array?

Can someone help me with storing a value from an HTML input field into a JavaScript array after a button click, and then displaying that array data on the screen? Here is the HTML code I am currently working with: <!DOCTYPE HTML> <html> < ...

Is there a way to determine if content is present within a given div element?

I have created a sample code where clicking on the "Next" button displays the next content of the page. However, if you click one more time on it when there is no content left, an empty page is shown. How can I determine whether content is available insi ...

Issue with jQuery click event not firing on multiple buttons with identical names

These are the two buttons that appear multiple times but do not function: <button name='btnEditar' class='btn btn-outline-success me-4' data-bs-toggle='modal' data-bs-target='#staticBackdrop'><i class=&a ...

How can I append a hash to a URL using JavaScript without causing the page to scroll?

Is it possible to add a hash to the URL without scrolling the page using JavaScript? I navigate to the page I scroll down I click on a link that adds a hash (for example: http://www.example.com/#test) The page should not scroll back to the top. What is ...

Having issues setting a property value on a Mongoose result in a Node.js application

Hello there, I am currently working with a MongoDB object retrieved via a findById method, and I need to convert the _id within this object from an ObjectID type to a string. I have developed the following function: student: async (parent, { _id }, ...

automatically loading data using jquery

I am currently utilizing a windows service along with an html+j query page to interact with a web service. Whenever a Document is scanned on our device, I aim to display: name, country, and Passport number on our webpage. Although I have successfully a ...

What steps are needed to successfully execute the generateHash function?

block.js The file block.js contains a function called generateHash, within which I am struggling to implement Promises for calculating the hash asynchronously and updating the hash property. class Block { constructor(data){ this.id = ...

Obtain a numerical output from a selection of numbers

I am facing a simple problem that I can't solve due to my lack of knowledge and have not been able to find any solution online. What I want to achieve is: Create a "value 1" from an array of integers. Generate a random "value 2". Check if the rando ...

How to update icon for fa-play using Javascript in HTML5

I recently added an autoplay audio feature to my website. I would like to implement the functionality to pause and play the music, while also toggling the icon to fa-play at the same time. This is the HTML code I am using: <script type="text/javascri ...

Should commas be used in variables?

Could this be converted in a different way? $('#id').testfunction({ 'source' : [ {'source':'pathimage.jpg','title':'Title 1','description':'This is a description 1.'}, ...