19

I have a couple of HTML select's (dropdowns) that are populated from a Firebase node called "states" (see image below). Upon choosing a city, the below function fires and should retrieve all meetings occurring in that City. There is a separate "meetings" node and each meeting has various key/value pairs such as street, time, etc.

I (think that I) want to use Promise.all because I want to do a Firebase read (a .once on each meetingID) inside the DataSnapshot.forEach. Below does not work.

function loadMeetings(city,state){
    //$('#meetingsTable').empty();
    var reads = [];
    ref.child('states').child(state).child(city).once('value').then(function(snapshot) {
        snapshot.forEach(function(childSnapshot) {
            var id = childSnapshot.key();
            var dfd = ref.child('meetings').child(id).once('value').then(function(snap) {
                // The Promise was fulfilled.
            }, function(error) {
                // The Promise was rejected.
                console.error(error);
            });
            reads.push( dfd );
        });       
    }, function(error) {
        // The Promise was rejected.
        console.error(error);
    });

    Promise.all(reads).then(function(values) { 
      console.log(values); // [snap, snap, snap] 
    });
}

{
  "geofire" : {
    "25dbab9c-8e4e-45ce-a69b-8641b6579560" : {
      ".priority" : "9q5cc9ye4w",
      "g" : "9q5cc9ye4w",
      "l" : [ 34.0677809, -118.4016105 ]
    },
    "3d2c7948-16e5-466c-b0d8-0a9e24ed7529" : {
      ".priority" : "7zzzzzzzzz",
      "g" : "7zzzzzzzzz",
      "l" : [ 0, 0 ]
    },
    "3fc846d4-7e55-4134-a0f5-9393aaf02269" : {
      ".priority" : "dhyy1zhnu1",
      "g" : "dhyy1zhnu1",
      "l" : [ 27.8130538, -80.42524100000003 ]
    },
    "5952bd9f-8438-44b0-addb-a5b806dab5da" : {
      ".priority" : "9vw1zzv421",
      "g" : "9vw1zzv421",
      "l" : [ 31.288082, -92.46505450000001 ]
    },
    "7001c8a7-c4f0-44ba-a4fc-2dba32097cc6" : {
      ".priority" : "9vqe68qs06",
      "g" : "9vqe68qs06",
      "l" : [ 30.1046126, -91.99056969999998 ]
    },
    "ecb350d6-6664-4f95-9c1c-2fd1d2f11a40" : {
      ".priority" : "9vrk9tstc9",
      "g" : "9vrk9tstc9",
      "l" : [ 30.353474, -90.98251599999998 ]
    }
  },
  "markup" : {
    "addMeeting" : "<form class=\"outline\"><div class=\"row\"><h1 class=\"blue topTitle col-xs-10 col-xs-offset-1 col-md-4 col-md-offset-4\">New Meeting</h1></div><br><div class=\"form-group row\"><div class=\"col-xs-10 col-xs-offset-1 col-md-3 col-md-offset-2\"> <input type=\"text\" class=\"form-control\" id=\"meetingName\" placeholder=\"Meeting Name\"> </div><div class=\"col-xs-10 col-xs-offset-1 col-md-4 col-md-pull-1\"> <input type=\"text\" class=\"form-control\" id=\"meetingStreet\" placeholder=\"Street\" required> </div></div><div class=\"form-group row\"><div class=\"col-xs-10 col-xs-offset-1 col-md-3 col-md-offset-2\"> <input type=\"text\" class=\"form-control\" id=\"meetingCity\" placeholder=\"City\" required> </div><div class=\"col-xs-10 col-xs-offset-1 col-md-2 col-md-pull-1\"> <select class=\"form-control c-select\" id=\"meetingState\" required><option>Alabama </option><option>Alaska</option><option>Arizona</option><option>Arkansas</option><option>California</option><option>Colorado</option><option>Connecticut</option><option>Delaware</option><option>Florida</option><option>Georgia</option><option>Hawaii</option><option>Idaho</option><option>Illinois</option><option>Indiana</option><option>Iowa</option><option>Kansas</option><option>Kentucky</option><option>Louisiana</option><option>Maine</option><option>Maryland</option><option>Massachusetts</option><option>Michigan</option><option>Minnesota</option><option>Mississippi</option><option>Missouri</option><option>Montana</option><option>Nebraska</option><option>Nevada</option><option>New Hampshire</option><option>New Jersey</option><option>New Mexico</option><option>New York</option><option>North Carolina</option><option>North Dakota</option><option>Ohio</option><option>Oklahoma</option><option>Oregon</option><option>Pennsylvania</option><option>Rhode Island</option><option>South Carolina</option><option>South Dakota</option><option>Tennessee</option><option>Texas</option><option>Utah</option><option>Vermont</option><option>Virginia</option><option>Washington</option><option>West Virginia</option><option>Wisconsin</option><option>Wyoming</option></select></div><div class=\"col-xs-10 col-xs-offset-1 col-md-2 col-md-pull-2\"> <input type=\"text\" class=\"form-control\" id=\"meetingZip\" placeholder=\"ZIP\" required> </div></div><div class=\"form-group row\"><div class=\"col-xs-5 col-xs-offset-1 col-md-2 col-md-offset-2\"> <input type=\"text\" class=\"form-control\" id=\"latitude\" placeholder=\"latitude\" disabled> </div><div class=\"col-xs-5 col-md-2 pull-left\"> <input type=\"text\" class=\"form-control\" id=\"longitude\" placeholder=\"longitude\" disabled> </div></div><div class=\"form-group row\"><div class=\"col-xs-10 col-xs-offset-1 col-md-2 col-md-offset-2\"><select class=\"form-control c-select\" id=\"weekday\"><option>Sunday</option><option>Monday</option><option>Tuesday</option><option>Wednesday</option><option>Thursday</option><option>Friday</option><option>Saturday</option></select></div><div class=\"col-xs-10 col-xs-offset-1 col-md-3 col-md-pull-1\"><div class=\"form-inline\"><div class=\"form-group\"><select class=\"form-control c-select\" id=\"hour\"><option>1</option><option>2</option><option>3</option><option>4</option><option>5</option><option>6</option><option>7</option><option>8</option><option>9</option><option>10</option><option>11</option><option>12</option></select><select class=\"form-control c-select\" id=\"minute\"><option>:00</option><option>:15</option><option>:30</option><option>:45</option></select><select class=\"form-control c-select\" id=\"timeframe\"><option>AM</option><option>PM</option></select></div></div></div></div><div class=\"form-group row\"><div class=\"col-xs-10 col-xs-offset-1 col-md-4 col-md-offset-2\"> <label class=\"radio-inline c-input c-radio\"> <input type=\"radio\" name=\"meetingType\" id=\"openMeeting\"> <span class=\"c-indicator\"></span> Open Meeting </label> <label class=\"radio-inline c-input c-radio\"> <input type=\"radio\" name=\"meetingType\" id=\"closedMeeting\" checked> <span class=\"c-indicator\"></span> Closed Meeting </label> </div></div><div class=\"form-group row\"><div class=\"col-xs-5 col-xs-offset-1 col-md-2 col-md-offset-2\"> <label class=\"c-input c-checkbox\"> <input type=\"checkbox\" id=\"mensOnly\"> <span class=\"c-indicator\"></span> Mens Only </label><br><label class=\"c-input c-checkbox\"> <input type=\"checkbox\" id=\"womensOnly\"> <span class=\"c-indicator\"></span> Womens Only </label><br><label class=\"c-input c-checkbox\"> <input type=\"checkbox\" id=\"childcare\"> <span class=\"c-indicator\"></span> Childcare </label> </div><div class=\"col-xs-5 col-xs-offset-1 col-md-2 col-md-pull-1\"> <label class=\"c-input c-checkbox\"> <input type=\"checkbox\" id=\"meditation\"> <span class=\"c-indicator\"></span> Meditation </label><br><label class=\"c-input c-checkbox\"> <input type=\"checkbox\" id=\"speaker\"> <span class=\"c-indicator\"></span> Speaker </label><br><label class=\"c-input c-checkbox\"> <input type=\"checkbox\" id=\"step\"> <span class=\"c-indicator\"></span> Step </label> </div></div><div class=\"form-group row\"><div class=\"col-xs-5 col-xs-offset-1 col-md-2 col-md-offset-2\"> <label class=\"c-input c-checkbox\"> <input type=\"checkbox\" id=\"spanish\"> <span class=\"c-indicator\"></span> Español </label><br><label class=\"c-input c-checkbox\"> <input type=\"checkbox\" id=\"bigBook\"> <span class=\"c-indicator\"></span> Big Book </label><br><label class=\"c-input c-checkbox\"> <input type=\"checkbox\" id=\"discussion\"> <span class=\"c-indicator\"></span> Discussion </label> </div><div class=\"col-xs-5 col-xs-offset-1 col-md-2 col-md-pull-1\"> <label class=\"c-input c-checkbox\"> <input type=\"checkbox\" id=\"tradition\"> <span class=\"c-indicator\"></span> Tradition </label><br><label class=\"c-input c-checkbox\"> <input type=\"checkbox\" id=\"beginner\"> <span class=\"c-indicator\"></span> Beginner </label> </div></div><div class=\"form-group row\"><div class=\"col-xs-5 col-xs-offset-8 col-md-2 col-md-offset-8\"> <input class=\"btn btn-primary\" type=\"submit\" id=\"submit\"></input> </div></div></form>",
    "admin" : "<ul id=\"tabs\" class=\"nav nav-tabs\"> <li class=\"nav-item\"> <a data-toggle=\"tab\" class=\"nav-link active\" href=\"#adminWelcome\" role=\"tab\">Welcome</a> </li><li class=\"nav-item dropdown\"> <a class=\"nav-link dropdown-toggle\" data-toggle=\"dropdown\" href=\"#\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\">Meetings</a> <div class=\"dropdown-menu\"> <a data-toggle=\"tab\" class=\"dropdown-item\" href=\"#addMeeting\">Add</a> <a data-toggle=\"tab\" class=\"dropdown-item\" href=\"#manageMeeting\">Manage</a> </div></li><li class=\"nav-item dropdown\"> <a class=\"nav-link dropdown-toggle\" data-toggle=\"dropdown\" href=\"#\" role=\"button\" aria-haspopup=\"true\" aria-expanded=\"false\">Users</a> <div class=\"dropdown-menu\"> <a data-toggle=\"tab\" class=\"dropdown-item\" href=\"#addUser\">Add</a> <a data-toggle=\"tab\" class=\"dropdown-item\" href=\"#manageUser\">Manage</a> </div></li></ul> <div class=\"tab-content\"> <div id=\"adminWelcome\" class=\"tab-pane fade in active\" role=\"tabpanel\"> <h3 class=\"topTitle\">Welcome.</h3><div class=\"loader\"><img src=\"images/loading.gif\"><p class=\"blue\">Running Scripts...</p></div><script>adminInit();</script> </div><div id=\"addMeeting\" class=\"tab-pane fade\" role=\"tabpanel\"><div class=\"loader\"><img src=\"images/loading.gif\"><p class=\"blue\">Running Scripts...</p></div></div><div id=\"manageMeeting\" class=\"tab-pane fade\" role=\"tabpanel\"><div class=\"loader\"><img src=\"images/loading.gif\"><p class=\"blue\">Running Scripts...</p></div></div><div id=\"addUser\" class=\"tab-pane fade\" role=\"tabpanel\"><div class=\"loader\"><img src=\"images/loading.gif\"><p class=\"blue\">Running Scripts...</p></div></div><div id=\"manageUser\" class=\"tab-pane fade\" role=\"tabpanel\"><div class=\"loader\"><img src=\"images/loading.gif\"><p class=\"blue\">Running Scripts...</p></div></div></div>",
    "adminWelcome" : "<p>This is the admin welcome pane</p>",
    "login" : "<div class=\"row topMargin myLogin col-xs-10 col-xs-offset-1 col-md-6 col-md-offset-3\"><br><h1 class=\"\">Log In</h1><br><div class=\"btn-group-vertical\" role=\"group\"><button class=\"btn btn-secondary myButton\" id=\"facebook\"><img src=\"images/facebook.png\" class=\"middle\" alt=\"Facebook logo\" height=\"24\"> Facebook</button><button class=\"btn btn-secondary myButton\" id=\"google\"><img src=\"images/google.png\" class=\"middle\" alt=\"Google logo\" height=\"24\"> Google</button><button class=\"btn btn-secondary myButton\" id=\"twitter\"><img src=\"images/twitter.png\" class=\"middle\" alt=\"Twitter logo\" height=\"24\"> Twitter</button></div><br><br><br></div>",
    "manageMeeting" : "<form class=\"form-inline outline\"><div class=\"form-group\"><label for=\"ddState\">Filter&nbsp; </label><select class=\"form-control\" id=\"ddState\" disabled></select></div><div class=\"form-group\"><label for=\"ddState\">&nbsp;&nbsp;&nbsp; </label><select class=\"form-control state\" id=\"ddCity\" disabled></select></div></form>"
  },
  "meetings" : {
    "25dbab9c-8e4e-45ce-a69b-8641b6579560" : {
      "author" : "Ron Royston",
      "beginner" : true,
      "bigBook" : true,
      "childcare" : false,
      "city" : "los angeles",
      "day" : "sunday",
      "discussion" : false,
      "hour" : "4",
      "key" : "25dbab9c-8e4e-45ce-a69b-8641b6579560",
      "latitude" : 34.0677809,
      "layer" : "",
      "longitude" : -118.4016105,
      "meditation" : false,
      "meetingOpen" : false,
      "min" : ":00",
      "name" : "highrise",
      "onlyMen" : false,
      "onlyWomen" : true,
      "spanish" : true,
      "speaker" : false,
      "state" : "california",
      "step" : false,
      "street" : "111 rodeo",
      "timeframe" : "pm",
      "timestamp" : 1457470568863,
      "tradition" : true,
      "type" : "",
      "user" : "facebook:196986260658947",
      "zip" : "90210"
    },
    "3d2c7948-16e5-466c-b0d8-0a9e24ed7529" : {
      "author" : "Ron Royston",
      "beginner" : false,
      "bigBook" : false,
      "childcare" : false,
      "city" : "baton rouge",
      "day" : "sunday",
      "discussion" : false,
      "hour" : "1",
      "key" : "3d2c7948-16e5-466c-b0d8-0a9e24ed7529",
      "latitude" : 0,
      "layer" : "",
      "longitude" : 0,
      "meditation" : false,
      "meetingOpen" : false,
      "min" : ":00",
      "name" : "asdf",
      "onlyMen" : false,
      "onlyWomen" : false,
      "spanish" : false,
      "speaker" : false,
      "state" : "louisiana",
      "step" : false,
      "street" : "234 kjhkj",
      "timeframe" : "am",
      "timestamp" : 1457470215505,
      "tradition" : false,
      "type" : "",
      "user" : "facebook:196986260658947",
      "zip" : "70817"
    },
    "3fc846d4-7e55-4134-a0f5-9393aaf02269" : {
      "author" : "Ron Royston",
      "beginner" : false,
      "bigBook" : true,
      "childcare" : true,
      "city" : "miami",
      "day" : "sunday",
      "discussion" : true,
      "hour" : "1",
      "key" : "3fc846d4-7e55-4134-a0f5-9393aaf02269",
      "latitude" : 27.8130538,
      "layer" : "",
      "longitude" : -80.42524100000003,
      "meditation" : false,
      "meetingOpen" : false,
      "min" : ":00",
      "name" : "beach",
      "onlyMen" : false,
      "onlyWomen" : false,
      "spanish" : true,
      "speaker" : false,
      "state" : "florida",
      "step" : false,
      "street" : "120 a1a",
      "timeframe" : "am",
      "timestamp" : 1457470499310,
      "tradition" : false,
      "type" : "",
      "user" : "facebook:196986260658947",
      "zip" : "33101"
    },
    "5952bd9f-8438-44b0-addb-a5b806dab5da" : {
      "author" : "Ron Royston",
      "beginner" : true,
      "bigBook" : false,
      "childcare" : false,
      "city" : "alexandria",
      "day" : "sunday",
      "discussion" : false,
      "hour" : "1",
      "key" : "5952bd9f-8438-44b0-addb-a5b806dab5da",
      "latitude" : 31.288082,
      "layer" : "",
      "longitude" : -92.46505450000001,
      "meditation" : false,
      "meetingOpen" : false,
      "min" : ":00",
      "name" : "howdy",
      "onlyMen" : false,
      "onlyWomen" : false,
      "spanish" : false,
      "speaker" : false,
      "state" : "louisiana",
      "step" : false,
      "street" : "5676 city park",
      "timeframe" : "am",
      "timestamp" : 1457470284850,
      "tradition" : true,
      "type" : "",
      "user" : "facebook:196986260658947",
      "zip" : "71301"
    },
    "7001c8a7-c4f0-44ba-a4fc-2dba32097cc6" : {
      "author" : "Ron Royston",
      "beginner" : false,
      "bigBook" : false,
      "childcare" : false,
      "city" : "lafayette",
      "day" : "sunday",
      "discussion" : false,
      "hour" : "1",
      "key" : "7001c8a7-c4f0-44ba-a4fc-2dba32097cc6",
      "latitude" : 30.1046126,
      "layer" : "",
      "longitude" : -91.99056969999998,
      "meditation" : false,
      "meetingOpen" : false,
      "min" : ":00",
      "name" : "test3",
      "onlyMen" : false,
      "onlyWomen" : false,
      "spanish" : false,
      "speaker" : false,
      "state" : "louisiana",
      "step" : false,
      "street" : "234 kjhkj",
      "timeframe" : "am",
      "timestamp" : 1457470252872,
      "tradition" : false,
      "type" : "",
      "user" : "facebook:196986260658947",
      "zip" : "70500"
    },
    "ecb350d6-6664-4f95-9c1c-2fd1d2f11a40" : {
      "author" : "Ron Royston",
      "beginner" : false,
      "bigBook" : false,
      "childcare" : false,
      "city" : "baton rouge",
      "day" : "sunday",
      "discussion" : false,
      "hour" : "5",
      "key" : "ecb350d6-6664-4f95-9c1c-2fd1d2f11a40",
      "latitude" : 30.353474,
      "layer" : "",
      "longitude" : -90.98251599999998,
      "meditation" : true,
      "meetingOpen" : false,
      "min" : ":00",
      "name" : "test1",
      "onlyMen" : false,
      "onlyWomen" : false,
      "spanish" : false,
      "speaker" : true,
      "state" : "louisiana",
      "step" : false,
      "street" : "18432 lake iris",
      "timeframe" : "pm",
      "timestamp" : 1457470192281,
      "tradition" : false,
      "type" : "",
      "user" : "facebook:196986260658947",
      "zip" : "70817"
    }
  },
  "states" : {
    "california " : {
      "los angeles" : {
        "25dbab9c-8e4e-45ce-a69b-8641b6579560" : true
      }
    },
    "florida " : {
      "miami" : {
        "3fc846d4-7e55-4134-a0f5-9393aaf02269" : true
      }
    },
    "louisiana " : {
      "alexandria" : {
        "5952bd9f-8438-44b0-addb-a5b806dab5da" : true
      },
      "baton rouge" : {
        "3d2c7948-16e5-466c-b0d8-0a9e24ed7529" : true,
        "ecb350d6-6664-4f95-9c1c-2fd1d2f11a40" : true
      },
      "lafayette" : {
        "7001c8a7-c4f0-44ba-a4fc-2dba32097cc6" : true
      }
    }
  }
}

enter image description here

Ronnie Royston
  • 16,778
  • 6
  • 77
  • 91
  • You've included a picture of the JSON tree in your question. Please replace that with the actual JSON as text, which you can easily get by clicking the Export button in your Firebase database. Having the JSON as text makes it searchable, allows us to easily use it to test with your actual data and use it in our answer and in general is just a Good Thing to do. – Frank van Puffelen Mar 09 '16 at 02:00
  • Done. I even tried var promisedMeetings = arr.map(loadMeeting); Promise.all(promisedMeetings).then - where loadMeeting is a .once call. No luck. – Ronnie Royston Mar 09 '16 at 15:55
  • Why on earth do you have a space after the state names? `"california " ` – Frank van Puffelen Mar 09 '16 at 17:06
  • fixed and edited snippet/json. must have forgotten to trim list i grabbed. – Ronnie Royston Mar 09 '16 at 17:48

1 Answers1

35

You have to execute the Promise.all after you filled the array with promises, i.e. inside the then callback:

function loadMeetings(city,state) {
    //$('#meetingsTable').empty();
    return ref.child('states').child(state).child(city).once('value').then(function(snapshot) {
        var reads = [];
//      ^^^^^^^^^^^^^^
        snapshot.forEach(function(childSnapshot) {
            var id = childSnapshot.key;
            var promise = ref.child('meetings').child(id).once('value').then(function(snap) {
                // The Promise was fulfilled.
            }, function(error) {
                // The Promise was rejected.
                console.error(error);
            });
            reads.push(promise);
        });
        return Promise.all(reads);
//      ^^^^^^^^^^^^^^^^^
    }, function(error) {
        // The Promise was rejected.
        console.error(error);
    }).then(function(values) { 
        console.log(values); // [snap, snap, snap] 
    });
}
nathancahill
  • 10,452
  • 9
  • 51
  • 91
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • 1
    I'm not getting anything in the final values. undefined. – Ronnie Royston Mar 08 '16 at 23:39
  • 1
    That means you're returning `undefined` (or don't `return` anything) from the `then` callback where you are creating the promises you're pushing into `reads`. If you just want to `return snap;` there, omit the callback completely. – Bergi Mar 09 '16 at 00:09
  • @Bergi the `snapshot` variable is a [DataSnapshot object from the Firebase JavaScript SDK](https://www.firebase.com/docs/web/api/datasnapshot/). While it implements `forEach()` it doesn't implement `map()`. – Frank van Puffelen Mar 09 '16 at 02:16
  • 1
    Working jsbin of Bergi's code: http://jsbin.com/hotemaquho/edit?js,console. The only change is that you need to ensure you return something from the inner `then()`. – Frank van Puffelen Mar 09 '16 at 17:11
  • 3
    You also have to change childSnapshot.key(); to childSnapshot.key; – Haves Aug 27 '17 at 12:21
  • @Haves no idea, I just took the OP's code from the question. – Bergi Aug 27 '17 at 12:47
  • I have tried all kinds of solutions for 2 days but I have not been successful. Finally I solved it thanks to your solution! Thanks @Bergi – Mustafa Feb 10 '20 at 14:54