Skip to content

Instantly share code, notes, and snippets.

@iclems
Last active June 21, 2018 09:48
Show Gist options
  • Save iclems/8300469 to your computer and use it in GitHub Desktop.
Save iclems/8300469 to your computer and use it in GitHub Desktop.
This snippet enables to iterate over a Firebase reference in a non-blocking way. If you need to iterate over a large reference, a child_added query may block your Firebase as it will query the whole data before iteration. With this snippet, children are retrieved one by one, making it slower / safer.
// By Clément Wehrung
function Iterator(queueRef, processingCallback) {
this.queueRef = queueRef;
this.processingCallback = processingCallback;
this.processed = {};
this.processNext();
}
Iterator.prototype.processNext = function() {
var priority = this.currentItem ? this.currentItem.getPriority() : undefined,
name = this.currentItem ? this.currentItem.name() : undefined;
this.queueRef.startAt(priority, name).limit(2).once("value", function(listSnap) {
listSnap.forEach(function(snap) {
var name = snap.name();
if (this.processed[name]) return;
this.processingCallback( snap, function() {
if (this.currentItem) {
setTimeout(this.processNext.bind(this), 0);
}
}.bind(this) );
this.currentItem = snap;
this.processed[ name ] = true;
}.bind(this));
}, this);
}
module.exports = Iterator;
@thinkloop
Copy link

Thanks for the helpful snippet! May I ask why this line is needed: if (this.processed[name]) return;

Why might children be processed twice with child_added?

@iclems
Copy link
Author

iclems commented Jan 21, 2014

The issue is that child_added will also be triggered with the last item. This line at least makes it obvious. I have in the meantime found one major issue with this version of the code, as the .on('child_added' are never switched off. Pushing a safer version as this one may lead to firebase using up to 100% CPU

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment