@@ -121,6 +121,7 @@ class DatabaseRef extends ReferenceBase {
121121
122122 this . db = db ;
123123 this . query = new DatabaseQuery ( this ) ;
124+ this . listeners = { } ;
124125
125126 // Aliases
126127 this . get = this . getAt ;
@@ -184,9 +185,13 @@ class DatabaseRef extends ReferenceBase {
184185 const path = this . dbPath ( ) ;
185186 const modifiers = this . dbModifiers ( ) ;
186187 return this . db . on ( path , evt , cb )
187- . then ( ( subscription ) => {
188+ . then ( ( { callback , subscriptions } ) => {
188189 return promisify ( 'on' , FirestackDatabase ) ( path , modifiers , evt )
189- . then ( ( ) => subscription ) ;
190+ . then ( ( ) => {
191+ this . listeners [ evt ] = subscriptions ;
192+ callback ( this ) ;
193+ return subscriptions ;
194+ } )
190195 } ) ;
191196 }
192197
@@ -200,7 +205,24 @@ class DatabaseRef extends ReferenceBase {
200205 off ( evt = '' ) {
201206 const path = this . dbPath ( ) ;
202207 return this . db . off ( path , evt )
203- . then ( ( ) => promisify ( 'off' , FirestackDatabase ) ( path , evt ) ) ;
208+ . then ( ( { callback, subscriptions} ) => {
209+ return promisify ( 'off' , FirestackDatabase ) ( path , evt )
210+ . then ( ( ) => {
211+ this . listeners [ evt ]
212+ delete this . listeners [ evt ] ;
213+ callback ( this ) ;
214+ return subscriptions ;
215+ } )
216+ } )
217+ . catch ( err => {
218+ console . error ( 'Never get here' , err ) ;
219+ } )
220+ }
221+
222+ cleanup ( ) {
223+ let promises = Object . keys ( this . listeners )
224+ . map ( key => this . off ( key ) )
225+ return Promise . all ( promises ) ;
204226 }
205227
206228 // Modifiers
@@ -289,7 +311,8 @@ export class Database extends Base {
289311 this . log . debug ( 'Created new Database instance' , this . options ) ;
290312
291313 this . persistenceEnabled = false ;
292- this . listener = null ;
314+ this . successListener = null ;
315+ this . errorListener = null ;
293316 this . refs = { } ;
294317 }
295318
@@ -317,69 +340,97 @@ export class Database extends Base {
317340
318341 handleDatabaseEvent ( evt ) {
319342 const body = evt . body ;
320- const path = evt . path ;
343+ const path = body . path ;
321344 const evtName = body . eventName ;
322345
323346 const subscriptions = dbSubscriptions [ path ] ;
324347
325348 if ( subscriptions ) {
326- const cb = subscriptions [ evtName ] ;
327- if ( cb && typeof ( cb ) === 'function' ) {
328- const snap = new DataSnapshot ( this , body . snapshot ) ;
329- this . log . debug ( 'database_event received' , path , evtName , snap ) ;
330- cb ( snap , body ) ;
331- }
349+ const cbs = subscriptions [ evtName ] ;
350+ cbs . forEach ( cb => {
351+ if ( cb && typeof ( cb ) === 'function' ) {
352+ const snap = new DataSnapshot ( this , body . snapshot ) ;
353+ this . log . debug ( 'database_event received' , path , evtName , snap ) ;
354+ cb ( snap , body ) ;
355+ }
356+ } ) ;
332357 }
333358 }
334359
360+ handleDatabaseError ( evt ) {
361+ this . log . debug ( 'handleDatabaseError ->' , evt ) ;
362+ }
363+
335364 on ( path , evt , cb ) {
336365 const key = this . _pathKey ( path ) ;
337366
338- if ( ! this . listener ) {
339- this . listener = FirestackDatabaseEvt
367+ if ( ! dbSubscriptions [ key ] ) {
368+ dbSubscriptions [ key ] = { } ;
369+ }
370+
371+ if ( ! dbSubscriptions [ key ] [ evt ] ) {
372+ dbSubscriptions [ key ] [ evt ] = [ ] ;
373+ }
374+ dbSubscriptions [ key ] [ evt ] . push ( cb ) ;
375+
376+ if ( ! this . successListener ) {
377+ this . successListener = FirestackDatabaseEvt
340378 . addListener (
341379 'database_event' ,
342380 this . handleDatabaseEvent . bind ( this ) ) ;
343381 }
344382
345- if ( ! dbSubscriptions [ key ] ) {
346- dbSubscriptions [ key ] = { } ;
383+ if ( ! this . errorListener ) {
384+ this . errorListener = FirestackDatabaseEvt
385+ . addListener (
386+ 'database_error' ,
387+ this . handleDatabaseError . bind ( this ) ) ;
347388 }
348389
349- dbSubscriptions [ key ] [ evt ] = cb ;
350- return Promise . resolve ( this . listener ) ;
390+ const callback = ( ref ) => {
391+ const key = this . _pathKey ( path ) ;
392+ this . refs [ key ] = ref ;
393+ }
394+ const subscriptions = [ this . successListener , this . errorListener ] ;
395+ return Promise . resolve ( { callback, subscriptions} ) ;
351396 }
352397
353398 off ( path , evt ) {
354- if ( this . listener ) {
355- const key = this . _pathKey ( path ) ;
356- // Remove subscription
357- if ( dbSubscriptions [ key ] ) {
358- if ( dbSubscriptions [ key ] [ evt ] ) {
359- delete dbSubscriptions [ key ] [ evt ] ;
399+ const key = this . _pathKey ( path ) ;
400+ // Remove subscription
401+ if ( dbSubscriptions [ key ] ) {
402+ if ( dbSubscriptions [ key ] [ evt ] ) {
403+ delete dbSubscriptions [ key ] [ evt ] ;
404+ }
405+ if ( Object . keys ( dbSubscriptions [ key ] ) . length <= 0 ) {
406+ // there are no more subscriptions
407+ // so we can unwatch
408+ delete dbSubscriptions [ key ]
409+ }
410+ if ( Object . keys ( dbSubscriptions ) . length == 0 ) {
411+ if ( this . successListener ) {
412+ this . successListener . remove ( ) ;
413+ this . successListener = null ;
360414 }
361-
362- if ( Object . keys ( dbSubscriptions ) . length <= 0 ) {
363- // there are no more subscriptions
364- // so we can unwatch
365- this . listener . remove ( ) ;
366- delete dbSubscriptions [ key ]
415+ if ( this . errorListener ) {
416+ this . errorListener . remove ( ) ;
417+ this . errorListener = null ;
367418 }
368419 }
369420 }
370- return Promise . resolve ( this . listener ) ;
421+ const callback = ( ref ) => {
422+ const key = this . _pathKey ( path ) ;
423+ delete this . refs [ key ] ;
424+ }
425+ const subscriptions = [ this . successListener , this . errorListener ] ;
426+ return Promise . resolve ( { callback, subscriptions} ) ;
371427 }
372428
373429 cleanup ( ) {
374- Object . keys ( dbSubscriptions ) . forEach ( key => {
375- Object . keys ( dbSubscriptions [ key ] ) . forEach ( evt => {
376- delete dbSubscriptions [ key ] [ evt ] ;
377- } )
378- } ) ;
379- this . listener . remove ( ) ;
380- Object . keys ( this . refs ) . forEach ( path => {
381- delete this . refs [ path ] ;
382- } ) ;
430+ let promises = Object . keys ( this . refs )
431+ . map ( key => this . refs [ key ] )
432+ . map ( ref => ref . cleanup ( ) )
433+ return Promise . all ( promises ) ;
383434 }
384435
385436 release ( ...path ) {
0 commit comments