Troubleshooting issue with JavaScript promise not functioning properly using resolve() method

I encountered an issue with promise usage in JavaScript. My objective was to retrieve data from firebase, store the results in an array, and then perform sorting on that array. Below is my code snippet:

    let promise = new Promise((resolve, reject) => {
    var query = firebase.database().ref('');
        query.once( 'value', data => {
            data.forEach(subtypeSnapshot => {
                var itemData = ;

                var query = firebase.database().ref('').child(itemKey);
                query.once( 'value', data => {
                    var itemDetail = ;
                    datasetarr.push();
                });
            }); 
            resolve(datasetarr);
        });             
    });

Upon inspecting the first console.log inside the promise, I observed the following output:

The successful retrieval from firebase indicates no issues with that part of the code. However, when attempting to store each element in the array using the line:

datasetarr.push({type: subtype, quantity: quantity});

Upon resolving the promise and checking the items within the array, nothing gets printed out during the for loop inside .then(). Any suggestions on how to address this?

Answer №1

It has been mentioned before that your Promise is being resolved too early.

To ensure all promises are resolved before resolving the wrapping Promise, you can utilize Promise.all. I have provided a simple example using functions returning Promises in place of a firebase database: https://jsfiddle.net/57b0gkLt/

As per the firebase documentation, query.once('value') yields a Promise, so this solution should work as expected.

EDIT: Implementation below

var datasetarr = [];
let promiseItemDataList = new Promise((resolve, reject) => {
var query = firebase.database().ref('receiptItemIDsByCategory').child(category);
    query.once( 'value', data => {
        var promises = []; // NEW LINE

        data.forEach(subtypeSnapshot => {
            var itemData = subtypeSnapshot.val();
            var itemKey = subtypeSnapshot.key;

            var query = firebase.database().ref('receiptItems').child(itemKey);
            var promise = query.once('value'); // NEW LINE
            promises.push(promise); // NEW LINE

            promise.then(data => { // .then instead of a callback
                var itemDetail = data.val();
                var subtype = itemDetail.type;
                var quantity = itemDetail.quantity;
                console.log('inside promise ' + subtype + ' ' + quantity);
                datasetarr.push({type: subtype, quantity: quantity});
            });
        }); 

        Promise.all(promises).then(() => resolve(datasetarr)); // NEW LINE
    });             
});

promiseItemDataList.then((arr) => {
    for(var i = 0; i < arr.length; i++){
        console.log('outside promise ' + arr[i].type + ' ' + arr[i].quantity);
    }
});

Answer №2

The initial async call to retrieve the first set of data was executed correctly, however, subsequent calls triggered by the .forEach loop encountered issues.

query.once( 'value', data => {
    var itemDetail = data.val();
    var subtype = itemDetail.type;
    var quantity = itemDetail.quantity;
    console.log('processing promise ' + subtype + ' ' + quantity);
    datasetarr.push({type: subtype, quantity: quantity});
});

The problem arises from resolving the promise before all the async calls are completed.

It seems that the query.once function is not using promises or traditional callback functions in standard ways.

To address this issue, one workaround could be wrapping the asynchronous calls within a Promise object and then using Promise.all([list_of_promises]) to ensure that every call completes before resolving the main promise.

Pseudo code:

var datasetarr = [];
let promiseItemDataList = new Promise((resolve, reject) => {
    var query = firebase.database().ref('receiptItemIDsByCategory').child(category);
    query.once( 'value', data => {

        // Create an array of promises for each sub-item async call
        var get_data_promises = [];
        data.forEach(subtypeSnapshot => {
            get_data_promises.push(new Promise(function(resolve) {
                var itemData = subtypeSnapshot.val();
                var itemKey = subtypeSnapshot.key;
                var query = firebase.database().ref('receiptItems').child(itemKey);

                query.once( 'value', data => {
                    var itemDetail = data.val();
                    var subtype = itemDetail.type;
                    var quantity = itemDetail.quantity;
                    console.log('inside promise ' + subtype + ' ' + quantity);
                    datasetarr.push({type: subtype, quantity: quantity});
                    resolve("Done");
                });
        }))

        // Execute all promises and then resolve the main promise
        Promise.all(get_data_promises).done(function() { resolve(datasetarr); });
    });
});

Answer №3

let fetchItemsByCategory = (category) => {
    let query = firebase.database().ref('receiptItemIDsByCategory').child(category);

    query.once('value')
    .then((data) => {
        let promises = [];
        data.forEach(subtypeSnapshot => {
            let itemData = subtypeSnapshot.val();
            let itemKey = subtypeSnapshot.key;

            let subQuery = firebase.database().ref('receiptItems').child(itemKey);
            let p = subQuery.once( 'value', data => {
                        let itemDetail = data.val();
                        let subtype = itemDetail.type;
                        let quantity = itemDetail.quantity;
                        console.log('Processing promise for ' + subtype + ' with quantity ' + quantity);
                    });
            promises.push(p);
        });
        return promises;
    })
    .then(arrayOfPromises => {
        Promise.all(arrayOfPromises)
        .then(results => {
            console.log(results);
        });
    });
}

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

Menu rollout problem when clicking or hovering

I'm facing challenges in making my menu content appear when a user clicks or hovers over the hamburger menu. My app is built using Angular, and I've written some inline JavaScript and CSS to achieve this, but the results are not as expected. Here ...

Locate a user within an array in Angular 5 by inputting a specific character into a textarea before initiating the search

I'm currently facing a situation with my textarea component... <textarea [(ngModel)]="message" id="commentBox" placeholder="Add your comment here..."></textarea> Additionally, I have a user list that retrieves data from an external API l ...

An error is occurring with the URL request being made

I have implemented pagination and query search feature in my Ticket List Below is the code for the Ticket List Page: const [query, setQuery] = useState(""); function handleSearch(e) { console.log(e.target.value); setQuery(e.target.value); } ...

Inserting a singular deeply nested item within a collection

In order to achieve my goal, I am faced with the decision to either update the counters within the single nested object or insert the entire document containing the array with initialized counters. Here is an example of the document structure: { "_ ...

Assigning a unique date/time stamp to every MongoDB document when it is created

This is my second query regarding Node.js for today. It's getting late, and I need some assistance to quickly incorporate this function before calling it a night. I have developed a small Q&A application where I can interact with MongoDB to read and ...

Replace an NPM package with a completely different package

As per the official NPM documentation, utilizing the overrides feature in the package.json file allows for the substitution of a package with an entirely different one: Overrides serve as a means to swap out a package within your dependency hierarchy wit ...

The destroySlider() function of BxSlider fails to work due to either an undefined slider or a function that is not

I'm facing an issue with my carousel setup using bxslider. Here is the code snippet responsible for initializing the carousel: jQuery(document).ready(function() { var carouselWidth = 640; var carousel; var carousel_Config = { minSlides: 1, ...

The AngularJS controller does not have its array initialized

Creating a small dialog controller where questions, answers, and correct answer index can be added. The goal is to allow users to add multiple questions and save them in an array. Everything works smoothly until attempting to push the JSON data of the que ...

smoothly slides into view and playfully bounces

http://jsfiddle.net/E6cUF/ The concept involves a grey box sliding left from behind a green box after the page is fully loaded, with a slight bouncing effect if possible. Update: I created a new version inspired by modifications made by others on the jsf ...

There was an AJAX post error that occurred due to the refusal to set an unsafe header with the name "Connection"

My custom ajax function sends data to a PHP file, but I'm encountering two errors each time the data is posted: Refused to set unsafe header "Content-length" Refused to set unsafe header "Connection" Here is my code: function passposturl(url1 ...

how to extract the inner elements from an array in PHP

Here is the structure of my array: array(90) { [0]=> NULL [1]=> array(1) { [0]=> string(18) "2016-03-27 0:04:06" } [2]=> array(1) { [0]=> string(1) "8" } . . . [90]=> array(1) { [0]=> ...

"Encountering issues with pointers while trying to access an array that has been successfully

Here's a very simple code that works perfectly: void execute(int *array) { return; } int start() { int maxSize = 999*999; int arrays[maxSize][6]; return 0; } But, when I change the main function like this, it crashes. int initiali ...

TextGeometry failing to render

Currently experimenting with TextGeometry. Successfully implemented BoxGeometry, but encountering issues with TextGeometry. Experimenting with different material options like MeshNormalMeterial, however, still unable to resolve the issue var scene = new ...

Laravel and Vue collaborate for an intelligently designed autocomplete feature

Currently, I am troubleshooting an issue with a vue autocomplete feature on a laravel website. I have configured the route, controller, and blade. When I inspect the vue component and type in the input field, I can see the keywords I am typing in the cons ...

How do you go about installing the most recent version of a module through Private NPM?

When using a private npm registry, I have noticed that some common commands do not seem to be functioning properly: npm install without specifying a specific @version :: issue npm outdated :: issue npm update :: issue npm view <private-packag ...

Regular expression for eliminating the local path from a website address

I am facing a scenario where different formats of relative paths can occur, such as: const URL1 = "./hello-world" const URL2 = "../hello-world" const URL3 = "../../hello-world" const URL4 = "../../../hello-world" con ...

Updating data from an API within a div using AJAX calls in a React application

I have designed a React template to showcase live football scores in the following manner: const LiveScore = () => { const {direction} = useThemeProvider(); const [selectedDay, setSelectedDay] = useState(parseInt(dayjs().format('DD'))); retur ...

Having trouble getting a value from a textbox to PHP using jQuery - can anyone lend a hand?

<script type="text/javascript" src="http://code.jquery.com/jquery-1.5b1.js"></script> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.7/jquery-ui.min.js"></script> <input type="text" id= ...

Converting a D3 tooltip using i18next for multilingual support

Is there a method to utilize the data-i18n attribute with d3 tooltips? In other words, is there a way to make it functional? I currently have a tooltip: var tip = d3.tip() .attr("class", "tip") .offset([-10,50]) .html(function(d) { return "< ...

What is the best way to generate a new array from an existing array in C that replicates each element of the original array up to the first tab character?

I am trying to separate strings in an array that have been read from a file by copying them to a new array until reaching the first tab character. After that, I need to move on to the next element in the array. Is there a recommended method for accomplish ...