4
function updateServerList() {
    var i;

    for (i=0; i < servers.length; i++) {
     var server = servers[i];
     var ip = server['serverIp']


     var html = constructServer(i);
     var divId = '#server' + ip.replace(new RegExp("\\.", "mg"), "-");
     var visible = $(divId).find(".server_body").is(":visible");
     var div = $(divId);
     div.html(html);

     // Set div class.
     var prevState = div.attr('class').substring(7)
     if (prevState != server['state']) {

         if (server['state'] == 'ok') {
         console.debug(server);
         div.slideUp('fast', function(server) {
             $(this).removeClass();
             $(this).addClass('server_ok');
             var id = ipToId[server['serverIp']];
             console.debug(id);
             if (id == 0) {
             adjacentIp = servers[1]['serverIp'];
             adjacentDivId = '#server' + adjacentIp.replace(new RegExp('\\.', 'g'), '-');
             $(adjacentDivId).before(this);
             }
        }).delay(1000);
        div.slideDown();
        }
    }
}

console.debug shows server as being defined, but inside the anonymous function, server is not defined. What am I going wrong?

0

3 Answers 3

5

because server is an argument to the function, its masking the value of the server at the higher level. You need to either pass server to the function, or remove the function argument. I would do the latter, as slideUp doesn't give you a way to pass arguments. You could do it but its needlessly complicated; it would look something like the following

div.slideUp('fast', (function(server) { 
   return function(){ 
      // your stuff here, server is now 'closed in', i.e. in a closure
   }
})(server)); // <-- this server is the current value in the loop

what you are doing here is invoking a new function right away, passing in the argument server, and returning a new function that receives that value.

Sign up to request clarification or add additional context in comments.

5 Comments

How do I pass it to the function?
@AlexBliskovsky: you don't need to. You can just access it when you have declared it like that.
Just remove the argument server from the inner function; I don't believe those animation callbacks pass an argument, anyways.
The callback is inside a loop and by the time it is called, the value of server seems to have changed. I need the value of server at a specific point in time.
@AlexBliskovsky: if that's the case you should really make sure you post all relevant code in your question.
1
var server = servers[i];

var prevState = div.attr('class').substring(7);

if (prevState != server['state']) {

   if (server['state'] == 'ok') {
      console.debug(server);
      div.slideUp('fast', function() {
            ...
         var id = ipToId[server['serverIp']];
     }
}

Inside your anonymous function, "server" is still within the function scope. No need to pass it in as an argument.

Comments

1

The Quick Fix

// ...

div.slideUp('fast', function() { // `server` argument removed
    // ...
});

The Explanation

There is no need to pass server to the function. The anonymous function "closes" over the server variable.


This is merely a function declaration:

function (server) {...}

You aren't passing anything to the function yet, as it isn't being invoked yet! The (server) bit in a function declaration simply lets you name the arguments to your function. Only when you invoke the function can you pass arguments:

var name = "Jill";
var showName = function (name) {
    alert(name);
};

showName("Jack"); // alert box shows "Jack"
showName(); // alert box shows "undefined"

So, when you declare that the name of the first argument to your anonymous function is server, there is a name conflict which prevents the original from being accessible; the server in your anonymous function is whatever slideUp passes as the first argument, which, according to the documentation, is nothing, so server is now undefined.

If this is confusing (and I suspect it is), I would suggest reading about javascript closures. Here's a good place to get started.


Fun fact: you can actually access arguments, in order, without having any explicit names, by using Javascript's built in arguments array object inside a function:

var sum = function () {
    var i, total = 0;
    for(i = 0; i < arguments.length; ++i) {
        total = total + arguments[i];
    }
    return total ;
};

alert(sum(1,2,3)); // Displays "6"
alert(sum(1,2,3,4)); // Displays "10"
alert(sum(1,0,2,3)); // Displays "6"
alert(sum()); // Displays "0"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.