0

I tried to use this loop to read some urls to read their modified time:

var arr = [];

//... fill arr with push

for (var e in arr) {
        nodename=arr[e].hostname;
        node_json="/nodes/"+nodename;
        html +='<a href="'+node_json+'" target="_blank" id="host_'+nodename+'">data</a>';

        xhr = $.ajax({
            url: node_json,
            success: (function(nn) {
                $('#host_'+nn).append("last modified: " + xhr.getResponseHeader("Last-Modified"));
            })(nodename)
        });

This already works a bit i I comment out the success line: I get calls to all node-files, and in Firebug, I can see the different modified times in the header of the calls.

At first I had a closure, (see How to generate event handlers with loop in Javascript?) And I only got the last line modified with all results. that's why I try to put the action in a separate function.

But that gives:

ReferenceError: xhr is not defined
$('#host_'+nn).append("last modified: " + xhr.getResponseHeader("Last-Modified")...

How do I get xhr into that function?


I aslo tried:

...
        xhr[e] = $.ajax({
            url: node_json,
            success: add_result_to_info(nodename, e)
        });

    }
}
// outside loop
function add_result_to_info(nn, e) {
    $('#host_'+nn).append("last modified: " + xhr[e].getResponseHeader("Last-Modified"));
}

source of the AJAX call: Get the modified timestamp of a file with javascript

2
  • your closure code is b0rked - you're not passing a function reference to success, but instead undefined - that being the (non-existent) return value of (function(nn) ...)(nodename) Commented Jul 31, 2014 at 20:39
  • BTW, is arr really an array, or an object? Commented Jul 31, 2014 at 20:40

2 Answers 2

2

If arr is truly an array, just use .forEach or even better .map (with a shim on older browsers) to encapsulate each iteration's scope without the need for additional closures:

var xhrs = arr.map(function(e) {
    var nodename = e.hostname;
    var node_json = "/nodes/" + nodename;

    html +='<a href="'+node_json+'" target="_blank" id="host_'+nodename+'">data</a>';

    return $.ajax({
        url: node_json
    }).done(function(data, status, xhr) {
        $('#host_'+nodename).append("last modified: " + xhr.getResponseHeader("Last-Modified"));
    });
});

The reason to use var xhrs = arr.map() instead of .forEach is that you then (for free) get the ability to call yet another callback once every AJAX request has completed:

$.when.apply($, xhrs).then(function() {
     // woot!  They all finished
     ...
});
Sign up to request clarification or add additional context in comments.

Comments

1

your are directly executing the method and passing its result as the callback for the success callback.

the xhr is already passed as the 3rd argument so try

success: function(nn,status, xhr) {
            $('#host_'+nn).append("last modified: " + xhr.getResponseHeader("Last-Modified"));
        }

if you have to pass the nodename as well, the you need to use a function that returns a function

success: (function(nn){
              return function(data ,status, xhr) {
                 // you can use nodename here...
                 $('#host_'+nn).append("last modified: " + xhr.getResponseHeader("Last-Modified"));
            };
        })(nodename)

4 Comments

partly right, except that nn is his loop variable, not the AJAX result
@Alnitak, added a version for this case.
I already tried that before, but does't work. geíves huge errors, because the result data is in the error message
something with the whole response, I think, because now with the (function... ) it is not the correct syntax anymore with those prackets around. But I cannot test any further, cause the solution above worked.... Thanks for your help ;)

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.