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

Community
  • 1
  • 1
rubo77
  • 19,527
  • 31
  • 134
  • 226
  • 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)` – Alnitak Jul 31 '14 at 20:39
  • BTW, is `arr` really an array, or an object? – Alnitak Jul 31 '14 at 20:40

2 Answers2

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
     ...
});
Alnitak
  • 334,560
  • 70
  • 407
  • 495
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)
Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
  • partly right, except that `nn` is his loop variable, not the AJAX result – Alnitak Jul 31 '14 at 20:41
  • @Alnitak, added a version for this case. – Gabriele Petrioli Jul 31 '14 at 20:44
  • I already tried that before, but does't work. geíves huge errors, because the result data is in the error message – rubo77 Jul 31 '14 at 20:49
  • 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 ;) – rubo77 Jul 31 '14 at 21:06