2016-03-08 78 views
4

我有兩個HTML選擇的下拉列表,它們是從名爲「states」的Firebase節點填充的(請參見下圖)。在選擇城市時,以下功能會觸發,並應檢索在該城市發生的所有會議。有一個單獨的「會議」節點,每個會議都有各種鍵/值對,例如街道,時間等。Promise.all with Firebase DataSnapshot.forEach

我認爲我想使用Promise.all,因爲我想要做Firebase讀取DataSnapshot.forEach中的每個meetingID上的.once)。下面不起作用。

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

+0

你已經在你的問題中包含了JSON樹的圖片。請將實際的JSON替換爲文本,您可以通過點擊Firebase數據庫中的導出按鈕輕鬆獲取該文本。將JSON作爲文本可以搜索,使我們能夠輕鬆使用它來測試您的實際數據,並將其用於我們的答案中,並且通常只是一件好事。 –

+0

完成。我甚至嘗試過var promisedMeetings = arr.map(loadMeeting); Promise.all(promisedMeetings).then - 其中loadMeeting是一個.once調用。沒有運氣。 –

+0

爲什麼地名上有空位? '「加利福尼亞」' –

回答

10

你必須執行Promise.all你充滿了承諾的陣列,即後then回調中:

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] 
    }); 
} 

順便說一句,如果snapshot是一個數組,您可以使用map而不是forEach來簡化代碼。

+0

我沒有得到任何最終值。未定義。 –

+1

這意味着你從'then'回調函數中返回'undefined'(或者不要'返回'任何東西),在那裏你創建你正在推入'reads'的promise。如果您只想「返回」,請完全省略回調。 – Bergi

+0

@Bergi'snapshot'變量是[Firebase JavaScript SDK中的DataSnapshot對象](https://www.firebase.com/docs/web/api/datasnapshot/)。雖然它實現了'forEach()',它並沒有實現'map()'。 –