0

i wanted to get the data from two tables in firebase db the 1st table was

enter image description here

from here i want to get the next data from table based on the hospital_fk

enter image description here

this is the result it got on my json

enter image description here

and here is my script for getting the data..

router.get('', function(req, res){
    var booths = database.ref('booths');
    var hospital = database.ref('hospitals');

        booths.once('value', function (snapshot) {
            var dataSet = [];
            snapshot.forEach(function (childSnapshot) {
                    
                var childKey = childSnapshot.key;
                var fk = snapshot.child(childKey).val();
                
                hospital.child(childSnapshot.val().hospital_fk).on('value', hospital=>{
                var childData =  _.assign(fk, hospital.val());
                
                    dataSet.push({
                        childKey: childKey, 
                        childData: childData
                    });

                    res.json(dataSet);
                });
            });

            
        });
});

now my problem was only the first data is being returned and also getting an error.. says that FIREBASE WARNING: Exception was thrown by user callback. Error: Can't set headers after they are sent.

any idea on how to get all the records and what's the best approach on joining two tables.

Community
  • 1
  • 1
Lion Smith
  • 647
  • 3
  • 16
  • 48

1 Answers1

1

When you call res.json(dataSet) it sets a header that your response is JSON, and sends the JSON. You can only set headers on the response before sending data, so the second time you make this call, Node.js will rightfully throw an error saying that it can't set the header.

What you'll need to do is first gather all joined data into a single JSON response, and then send it in one go after you've loaded all of them. To do this you use a list of promises and Promise.all():

router.get('', function(req, res){
    var booths = database.ref('booths');
    var hospital = database.ref('hospitals');

    booths.once('value', function (snapshot) {
        var promises = [];
        snapshot.forEach(function (childSnapshot) {

            var childKey = childSnapshot.key;
            var fk = snapshot.child(childKey).val();

            var promise = hospital.child(childSnapshot.val().hospital_fk).once('value');

            promises.push(promise);
        });
        Promise.all(promises).then(function(snapshots) {
            var dataSet = [];
            snapshots.forEach(function(hospital) {

                var childData =  _.assign(hospital.key, hospital.val());

                dataSet.push({
                    childKey: hospital.key, 
                    childData: childData
                });

            });
            res.json(dataSet);
        });

    });
});

Now the code only calls res.json(dataSet) once, after it's gotten all of the hospital data.

You'll note that I also changed your on('value' to once('value', since I doubt you'll want to keep the listener active for more than just one read.

Frank van Puffelen
  • 565,676
  • 79
  • 828
  • 807
  • it returns an error `Unhandled promise rejection (rejection id: 1): ReferenceError: childKey is not defined Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit cod` – Lion Smith Jan 15 '18 at 03:23
  • cant get the `childKey` from the first loop.. how can i get the data from the first loop then pass it to the next loop?. – Lion Smith Jan 15 '18 at 05:05
  • Since you're loading the snapshot based on the `childKey`, you can just get it from the snapshot. I updated the code. – Frank van Puffelen Jan 15 '18 at 05:26
  • the json return was the id of hospital.. the result that i want was to join the two child data of booth and hospital.. based on the id of hospital from the booth.. and the childKey is the id of the booth.. – Lion Smith Jan 15 '18 at 05:35
  • how can i use the `childshnapshot.key` and `childsnapshot.val()` from the 1st loop inside `promise.all()` supposed to be the value of childData inside .push was the child data from the 1st table and and the 2nd table. – Lion Smith Jan 15 '18 at 06:01
  • See this answer for passing values from the first promise handler to the second: https://stackoverflow.com/a/48038588/209103 – Frank van Puffelen Jan 15 '18 at 17:01
  • thanks for giving me the info on how to pass the value from the first promise to the second.. that is what i really need.. can you modify your answer so that i can mark it as check.. – Lion Smith Jan 16 '18 at 03:31