Andrew Fan Andrew Fan - 14 days ago 5
Javascript Question

Javascript - Strange behavior with indexing object arrays

So I have a conundrum involving the following code:

$scope.getUserContact = function(data) {
var i;
for (i = 0; i < data.length; i += 1) {
$http({
method: 'GET',
url: [Removed]
}).then(function successCallback(response) {
alert(JSON.stringify(data));
alert(data.length);
alert(JSON.stringify(data[i]));
...
}, function errorCallback(response) {
});
}
}


First line spits out:

[
{
"listingId":"String",
...other Strings and ints ...
}
]


Basically, it spits out an array consisting of one object.

Second line spits out

1


As expected, the length of the array is 1.

Third line spits out

undefined


I just don't understand how indexing an array suddenly results in
undefined
instead of giving me the object at the index.

It may be notable that
data
is a parameter to a function.

Any help? I assume it's either a stupid error on my part or some strange and unknown behavior from the depths of JavaScript.

Answer

The problem is that the $http request is asynchronous so

  • first the loop will initialize all requests
  • then when i = data.length the requests will end and every callbacks will be called with the last value of i, not the one you wanted

You should do something like that to not use the same i in the callback

$scope.getUserContact = function(data) {
  var i;
  for (i = 0; i < data.length; i += 1) {
    doRequest(data, i);
  }
}

function doRequest(data, i) {
  $http({
    method: 'GET',
    url: [Removed]
  }).then(function successCallback(response) {
    alert(JSON.stringify(data));
    alert(data.length);
    alert(JSON.stringify(data[i]));
    ...
  }, function errorCallback(response) {});
}

Also if you want more control with your flow you should use the promises from $http and $q

$scope.getUserContact = function(data) {
  var requests = data.map(function(d, i) {
    return doRequest(data, i)
  });
  return $q.all(requests).then(function(requestsResults) {
    // do something when every requests have ended
  });
}

function doRequest(data, i) {
  return $http({
    method: 'GET',
    url: [Removed]
  }).then(function successCallback(response) {
    // do something when this request have ended
  }, function errorCallback(response) {});
}

Comments