Note that there are some explanatory texts on larger screens.

plurals
  1. POHow do I deal with two callbacks accessing a datastructure in javascript?
    text
    copied!<p><strong>Update 2:</strong> <em>I think this is a better explanation:</em></p> <p>I have two callbacks, and each is filling up an array. I want to merge these arrays somehow. The naive way to do it is to wait until the arrays are filled, then merge with a for loop. I can't do that because there's no real way to check if the callbacks are "done".</p> <p>The next step might be something like this: Each time an object is downloaded by a callback, it checks the merge array (called mixed), and sees if it contains a "partner" object. If it does: then merge into that partner object. If it doesn't, then insert that object. </p> <p>I'm worried about race conditions: callback 1 sees the array is empty, decides to insert into it, but then control switches to callback 2, which inserts first. Callback 1 should now merge instead of insert, but when control switches back, it inserts instead.</p> <p>What could help is if I could make an atomic "check and insert/merge" block of code. Is there a way to do that?</p> <hr> <p><strong>Update 1:</strong> Now with code, and more words!</p> <p>Thanks for your response, everyone. I went and tried to simplify the code as much as I could. </p> <p><strong>Words:</strong></p> <p>I have an array called mixed. Mixed should end up with: all objects of type (A), and if they have analogue objects of type (B) (also known as "private"s), they should be merged. </p> <p>That means using two functions that use callbacks - getAllA and getAllB. Right now, I call both, wait a bit manually, then run a for loop that does that merging.</p> <p>What I need to do is edit my code so that the merging happens in callbacks. However, I can't think of a way to do that merging in a way that doesn't create a race condition. </p> <p>Naively, I might want to first fill up mixed with objects of type A, then go iterate through the B objects and merge them as needed. However, I can't do that because there's no way to see if you're "done" with on("contact_added") in firebase. What I think I want is a concurrent array structure, but I don't know how to use a built-in one. I'm worried about making my own because I don't know how to check to if I did it wrong. Race conditions are tricky like that.</p> <p><strong>Now, the code:</strong> Here are the scripts you need to reference:</p> <p>And here's what I paste into the javascript console:</p> <pre><code> //Note: private ~~ B // public ~ A var me = 'IWwypRHWpDmydd30o-v'; var mixed = new Array(); var mixedNames = new Array(); var privates = new Object(); var callbackB = function(snapshot){ child = snapshot.val(); privates[snapshot.name()] = child; }; var callbackA = function(snapshot){ var listRef = snapshot.ref(); listRef.on('child_added', function (snapshot2) { child = snapshot2.val(); mixedNames.push(snapshot2.name()); mixed.push(child); }); }; var getAllB = function (callback, ownerid){ var priv = new Firebase('http://gamma.firebase.com/innermost/project/private/' + ownerid); priv.on('child_added', function (snapshot){ callback(snapshot); }); }; function getAllA(callback) { var pub = new Firebase('http://gamma.firebase.com/innermost/project/public'); pub.once('value', function (snapshot) { if (snapshot.val() === null) { alert('snapshot does not exist.'); } callback(snapshot); }); } getAllA(callbackA); getAllB(callbackB, me); //////wait for (b in privates){ var index = $.inArray(b, mixedNames); if (index &lt; 0){ //if there is no record with this name mixed.push(privates[b]); mixedNames.push(b); } else{ var pub = mixed[index]; var mutt = returnMixed(pub, privates[b]); mixed.splice(index,1,mutt); } }; </code></pre> <p>What I want to do is move the logic from the for loop into the callbacks, because if you run the for loop right away, the arrays won't be done downloading through the callbacks yet.</p> <hr> <p><em>The old entry:</em></p> <p>I have two callbacks accessing lists of data on Firebase. </p> <p>Callback 1 gets objects of type A. Callback 2 gets objects of type B.</p> <p>My goal - have an array that properly merges objects of type A and B. </p> <p>Most (but necessarily all) objects of type B have a "partner" object of type A. A few objects of type A have a partner object of type B.</p> <p>For each object pulled from Firebase, I want to see if their partner is in the array. If not, then insert. If so, then "merge" with the partner instead.</p> <p>I can't think of a way to do this without a concurrent data structure - but I don't know how to do that in Javascript. </p> <p>How can I either create that concurrent Array, or figure out a way to achieve my goal some other way?</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload