Skip to content

Commit

Permalink
fixed error when Firebase data is cached locally, caused some records…
Browse files Browse the repository at this point in the history
… to return synchronously with wrong keys and values. Simplified demo data.
  • Loading branch information
katowulf committed Mar 20, 2013
1 parent ef471bc commit 04460fb
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 21 deletions.
44 changes: 37 additions & 7 deletions FirebaseIndex.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ var FirebaseIndex;
case 'child_added':
fn = addEventListener(this.eventListeners[eventType], callback, context);
// mimic Firebase behavior by sending any pre-existing records when on('child_added') is invoked
notifyExistingRecs(this.childRefs, fn);
notifyExistingRecs(this.dataRef, this.childRefs, fn);
break;
case 'child_changed':
case 'child_removed':
Expand Down Expand Up @@ -266,7 +266,10 @@ var FirebaseIndex;

function notifyListeners(list, ss, key, prevId) {
list.forEach(function(o) {
o.fn(wrapSnap(ss, key), prevId);
// make the calls async so they match client expectations
// Firebase can call them synchonously if the data is already local
// which messes up Promise.progress() and any async callbacks
defer(function() { o.fn(wrapSnap(ss, key), prevId) });
});
}

Expand All @@ -280,17 +283,22 @@ var FirebaseIndex;
return fn;
}

function notifyExistingRecs(refs, callback) {
function notifyExistingRecs(dataPathFn, refs, callback) {
var key;
for (key in refs) {
if (refs.hasOwnProperty(key)) {
refs[key].ref.once('value', function(ss) {
if( ss.val() !== null ) { callback(ss); }
});
if (refs.hasOwnProperty(key) && refs[key].loaded) {
// must be external because key is mutable and we use it in a closure
getValAndNotify(dataPathFn(key), key, callback);
}
}
}

function getValAndNotify(ref, key, callback) {
ref.once('value', function(ss) {
if( ss.val() !== null ) { defer(function() { callback(wrapSnap(ss, key)); }); }
});
}

function storeChildRef(list, cb, ss, prevId) {
var key = ss.name();
var childRef = ss.ref();
Expand Down Expand Up @@ -345,6 +353,28 @@ var FirebaseIndex;
}
}

var defer;
if( typeof(_) === 'object' && _ && typeof(_.defer) === 'function' ) {
// if underscore is available, use it
defer = _.defer;
}
else {
// otherwise, hope setTimeout hasn't been tinkered with
defer = function(fn) {
return setTimeout(fn, 0);
}
}

/**
* Because we're getting the value from a random path, which could be a function, the keys may not match.
* For instance, our reference key could be group/member/1234 and our data path could be user/1234/public/widget,
* in which case, if we use ss.name() on the data path, we get a key of "widget" which is clearly not right.
* So this method normalizes the keys.
*
* @param {Firebase} ss reference to the data path
* @param {String} key key from the index
* @returns {*}
*/
function wrapSnap(ss, key) {
ss.name = function() { return key; };
return ss;
Expand Down
32 changes: 18 additions & 14 deletions demo/demo.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jQuery(function ($) {

// initialize our indexed data
var FB = new Firebase('https://i5ubv072aza.firebaseio-demo.com/');
var IDX = new FirebaseIndex(FB.child('indices/widgets'), FB.child('widgets'));
var IDX = new FirebaseIndex(FB.child('index'), FB.child('widgets'));

// refs for our DOM nodes
var $master = $('#master');
Expand Down Expand Up @@ -88,7 +88,13 @@ jQuery(function ($) {

function resortIndex(e) {
var $arrow = $(e.target), $el = $arrow.closest('li'), id = $el.attr('data-id'), pri = $el.find('input').val();
IDX.add(id, pri? parseInt(pri) : null);
if( parseInt(pri) == pri ) {
IDX.add(id, pri? parseInt(pri) : null);
}
else {
alert('must be a number for this demo');
$el.find('input').val(null);
}
}

/*****************************************
Expand All @@ -114,7 +120,7 @@ jQuery(function ($) {
}

function initIndex() {
var ref = FB.child('indices/widgets');
var ref = FB.child('index');

ref.on('child_added', function(ss, afterId) {
var id = ss.name();
Expand Down Expand Up @@ -175,17 +181,15 @@ jQuery(function ($) {
"charlie" : "it's yellow and conical",
"alpha" : "it's red and square"
},
"indices" : {
"widgets" : {
"delta" : {
".value" : 1,
".priority" : 100.0
},
"golf" : 1,
"alpha" : {
".value" : 1,
".priority" : 150.0
}
"index" : {
"delta" : {
".value" : 1,
".priority" : 100.0
},
"golf" : 1,
"alpha" : {
".value" : 1,
".priority" : 150.0
}
}
};
Expand Down

0 comments on commit 04460fb

Please sign in to comment.