0

I have 2 functions that each modify a parameter that is passed to them.

var data = [];

var DoStuff = function( $div , data )
{
    var $D = $div;
    var D = data;
    var socket = $.atmosphere;
    var stuff = {
        onMessage: function(message)
        { // when a message is asynch. received over websocket
            D.push( { "a": "b" } );
            D.push( { "y": "z" } );
            $D.append( JSON.stringify(D) );
            return message;
        }
    }

    this.start = function()
    {
        var socketStream = socket.subscribe( stuff );
        return socketStream;
    }
}

$(function(){

    var $div = $('#div');

    var doStuff = new DoStuff( $div , data );

    data.push( { "w": "x" } );

    $div.append( JSON.stringify(data) );

    var stream = doStuff.start();

});

Sometimes after everything is all said and done, the array data contains both objects:

data: [
    { "w": "x" },
    { "y": "z" }
]

But sometimes it contains only the first object:

data: [
    { "w": "x" }
]

If I put a breakpoint on DoStuff.a return true;, D usually contains both objects. But about 10% of the time, D does not contain the first object (only the second), YET, data contains only the first. D is a reference to data, so how can they be out of synch?

Edit I tried using setTimeout() to make each and then both push() wait, but that did not cause different outcome in any of the 3 cases.

I think it can't be a race condition because then something would get overwritten, but that's not happening. a:b and y:z are missing. If that were the case, either a:b or y:z should still be present (along with w:x).

Jakob Jingleheimer
  • 30,952
  • 27
  • 76
  • 126
  • 2
    FYI: JavaScript does not support passing by reference.. – Mike Christensen Oct 31 '13 at 19:14
  • @MikeChristensen, that is so not true: http://stackoverflow.com/a/13104500/758177 Also, if that were true, then data should never contain the values added to it via `D`. – Jakob Jingleheimer Oct 31 '13 at 19:17
  • 6
    Read the answer more carefully. The object is not passed by reference, the reference itself is passed by value; as is everything else in JavaScript. – Mike Christensen Oct 31 '13 at 19:18
  • @MikeChristensen you're totally wrong. `function ref(o) { o.foo = "bar"; }; var x = {}; ref(x); console.log(x.foo); // "bar"` – Mulan Oct 31 '13 at 19:20
  • 6
    @naomik - In this case, the reference in `x` is passed *by value* to the function `ref`. In other words, a new *copy* of that reference is made. The reference itself is passed by value. To prove this point, try setting `o` to something else within `ref` and see if it affects `x`. If the object was passed by reference, it would. – Mike Christensen Oct 31 '13 at 19:23
  • @MikeChristensen http://jsfiddle.net/jshado1/ZBVEk/ – Jakob Jingleheimer Oct 31 '13 at 19:25
  • 1
    @jacob - Looks valid to me, though passing a global into a function seems somewhat odd. You first push *bar* onto your array, then call `a()` which pushes *foo* onto the array, then you add those values (bar and foo) to `$log`. Next, you append those same values to `$log` again. Is this not the behavior you expect? – Mike Christensen Oct 31 '13 at 19:33
  • @MikeChristensen, yes, that is what I expect. However, when a websocket message comes in, _sometimes_ `data` does not receive the object pushed into it within `onMessage()` and the contents of `$D` does not contain the new data after everything is over. However, if I inspect `$D` in the debugger when this craziness happens, its `innerHTML` property **does** contain the new data but **does not** contain the data from outside. – Jakob Jingleheimer Oct 31 '13 at 19:37
  • @jacob - Yea, I'm not familiar enough with web sockets to comment. These sorts of things are often race conditions. I'm hoping someone else will have an answer that is helpful for you. I just thought I'd clear up the misconception of passing by reference, since it was on your title, and I think I've done my job here. – Mike Christensen Oct 31 '13 at 19:39
  • @MikeChristensen, if it was a race condition, the second object should replace the first, no? That never happens. The second object is always the one missing. – Jakob Jingleheimer Oct 31 '13 at 19:41
  • @jacob: You are wrong. There is NO pass by reference in JavaScript. – newacct Oct 31 '13 at 22:27
  • @naomik: You are wrong. There is NO pass by reference in JavaScript. – newacct Oct 31 '13 at 22:28

0 Answers0