-1

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.

Andrew Fan
  • 1,313
  • 5
  • 17
  • 29

1 Answers1

1

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) {});
}
user3
  • 740
  • 3
  • 15
  • I need to set data after receiving the results of all of the requests, so how would I have another callback run upon completion of all the calls to doRequest? – Andrew Fan Nov 18 '16 at 23:07
  • Actually, it's fine - I can update the data after every iteration. Thank you. – Andrew Fan Nov 18 '16 at 23:08
  • To wait for a call you can return the promise that $http is using (just a simple return), to wait for every calls you can use `$q.all` – user3 Nov 18 '16 at 23:09
  • I just edited to add links and an example of using the $http promise for that – user3 Nov 18 '16 at 23:17