@@ -121,6 +121,7 @@ class DatabaseRef extends ReferenceBase {
121
121
122
122
this . db = db ;
123
123
this . query = new DatabaseQuery ( this ) ;
124
+ this . listeners = { } ;
124
125
125
126
// Aliases
126
127
this . get = this . getAt ;
@@ -184,9 +185,13 @@ class DatabaseRef extends ReferenceBase {
184
185
const path = this . dbPath ( ) ;
185
186
const modifiers = this . dbModifiers ( ) ;
186
187
return this . db . on ( path , evt , cb )
187
- . then ( ( subscription ) => {
188
+ . then ( ( { callback , subscriptions } ) => {
188
189
return promisify ( 'on' , FirestackDatabase ) ( path , modifiers , evt )
189
- . then ( ( ) => subscription ) ;
190
+ . then ( ( ) => {
191
+ this . listeners [ evt ] = subscriptions ;
192
+ callback ( this ) ;
193
+ return subscriptions ;
194
+ } )
190
195
} ) ;
191
196
}
192
197
@@ -200,7 +205,24 @@ class DatabaseRef extends ReferenceBase {
200
205
off ( evt = '' ) {
201
206
const path = this . dbPath ( ) ;
202
207
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 ) ;
204
226
}
205
227
206
228
// Modifiers
@@ -289,7 +311,8 @@ export class Database extends Base {
289
311
this . log . debug ( 'Created new Database instance' , this . options ) ;
290
312
291
313
this . persistenceEnabled = false ;
292
- this . listener = null ;
314
+ this . successListener = null ;
315
+ this . errorListener = null ;
293
316
this . refs = { } ;
294
317
}
295
318
@@ -317,69 +340,97 @@ export class Database extends Base {
317
340
318
341
handleDatabaseEvent ( evt ) {
319
342
const body = evt . body ;
320
- const path = evt . path ;
343
+ const path = body . path ;
321
344
const evtName = body . eventName ;
322
345
323
346
const subscriptions = dbSubscriptions [ path ] ;
324
347
325
348
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
+ } ) ;
332
357
}
333
358
}
334
359
360
+ handleDatabaseError ( evt ) {
361
+ this . log . debug ( 'handleDatabaseError ->' , evt ) ;
362
+ }
363
+
335
364
on ( path , evt , cb ) {
336
365
const key = this . _pathKey ( path ) ;
337
366
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
340
378
. addListener (
341
379
'database_event' ,
342
380
this . handleDatabaseEvent . bind ( this ) ) ;
343
381
}
344
382
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 ) ) ;
347
388
}
348
389
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} ) ;
351
396
}
352
397
353
398
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 ;
360
414
}
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 ;
367
418
}
368
419
}
369
420
}
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} ) ;
371
427
}
372
428
373
429
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 ) ;
383
434
}
384
435
385
436
release ( ...path ) {
0 commit comments