Pass variables within a for in Javascript

1

I have the following code to pass parameters to a function:

function updateBar(id, type, title, idDash, urls){
    for(var i in urls){
      var url = urls[i].url+'/'+id;
      $.getJSON(url, function(data){
        var dataHarvest = data['return'];
        if(type === "Bar"){
          barChart(dataHarvest, title, type, idDash, urls[i].id, urls);
        }
      }); 
    }
  }

urls is an object that brings me query links and their id (These links are brought from a database).

When doing the route with the for , it works well because it queries me every url that I am sending and gets the data of each query that is being made.

The problem is that I want the function barChart() to send each of the ids of the object urls but only send me the last one, the other options are fine.

What I realize is that despite being the request GET within a for, does not take into account the route. that is:

When doing a console.log(urls[i].id); you should bring me 1 2 3 which are the ids, but it only brings me 3

I would like to know if there is a way to get all the ids when doing the path of the for or if there is a different way of doing this function that I am planning.

    
asked by Fabian Sierra 16.09.2016 в 17:29
source

3 answers

2

This is a classic problem that has to do with the fact that $.getJSON is an asynchronous function, so when the success code is executed, the values of the variables no longer match the values that were there at the time when the call was made to $.getJSON .

One possible solution would be to create a closure ( closure in English) and thus create a special scope that will preserve the values. Something like this:

function updateBar(id, type, title, idDash, urls){
    for(var i in urls){
        (function(i) {
            var url = urls[i].url;
            $.getJSON(url, function(data){
                var dataHarvest = data['return'];
                if(type === "Bar"){
                    barChart(dataHarvest, title, type, idDash, urls[i].id, urls);
                }
            }); 
        })(i);
    }
}
    
answered by 16.09.2016 / 17:59
source
2

The response of @ AlvaroMontoro is very good. With the arrival of ES6, the closures in this case can be avoided by using let in the control variable instead of var .

for(let url in urls) { ... }

The reason for this is because when you declare a variable with var it does not depend on the block where it is declared, if not, its scope is the function where it is found. In other words, var url transcends the for, and when it comes to receiving the callback, the loop has already completed its iteration. which does not make much sense if you think about it ...

(function a() {
  {
    var e = 123;
  }
  console.log(e); // imprime 123
})();

Conversely, let if you use a "block" scope, which limits it to the block where it is declared.

(function call(urls) {
  for(let url of urls) {
    $.getJSON(url, (resp) => {
      console.log(url); // mira lo que imprime
    });
  }
})(['http://api.fixer.io/latest', 
    '/api/arenas', 
    '/examples/avatar-api']);
    
answered by 16.09.2016 в 18:25
0

I recommend you verify that the requests are made correctly ..

You can verify it by adding console.log(url); before $.getJSON(url, function(data){ Maybe the problem is that the request is not completed, try to see if everything goes well with something like this:

console.log("Enviando peticion a: " + url);
$.getJSON(url, function(data) {
  var dataHarvest = data['return'];
        if(type === "Bar"){
          barChart(dataHarvest, title, type, idDash, urls[i].id, urls);
        }
}).error(function() { console.log("Error en obtener datos: " + url); });
    
answered by 16.09.2016 в 17:42