Daveh0
Daveh0

Reputation: 990

In Angular, what's the best way to persist data through an asynchronous call?

I have a controller with a for loop that make's HEAD requests for an array of URLs to check if the file exists. When I get the response from the HEAD request, i need the index number from the array that the request was based on.

var allFiles = [], files = [];
allFiles.push({"url":"http://www.example.com/foo","source":"source1"});
allFiles.push({"url":"http://www.example.com/bar","source":"home"});
allFiles.push({"url":"http://www.example.com/wtf","source":"outer space"});

for(var i=0,len=allFiles.length;i<len;i++) {
    $http.head(allFiles[i].url).then(function(response) {
        files.push(allFiles[VALUE_OF_i_AT_TIME_OF_REQUEST]);
   }
}

EDIT:
Because it is an asynchronous call, I cannot use i in place of VALUE_OF_i_AT_TIME_OF_REQUEST. Doing that results in i always being equal to len-1

I guess I can send the index number as data with the request and retrieve it from the response but for some reason that seems hack-ish to me.

Is there a better way?

Upvotes: 2

Views: 66

Answers (3)

Daveh0
Daveh0

Reputation: 990

I did something similar to @rob's suggestion and it seems to be doing the trick.

var allFiles = [], files = [];
allFiles.push({"url":"http://www.example.com/foo","source":"source1"});
allFiles.push({"url":"http://www.example.com/bar","source":"home"});
allFiles.push({"url":"http://www.example.com/wtf","source":"outer space"});

for(var i=0,len=allFiles.length;i<len;i++) {
    (function(i) {
        $http.head(allFiles[i].url).then(function(response) {
            files.push(allFiles[i]);
        }
    })(i);
}

Upvotes: 0

MattDionis
MattDionis

Reputation: 3616

I may be oversimplifying this (asynchronous code is still tricky to me), but could you set i to a new local variable j on each loop then reference j instead of i in files.push(allFiles[j]):

var allFiles = [], files = [];
allFiles.push({"url":"http://www.example.com/foo","source":"source1"});
allFiles.push({"url":"http://www.example.com/bar","source":"home"});
allFiles.push({"url":"http://www.example.com/wtf","source":"outer space"});

for(var i = 0, len = allFiles.length; i < len; i++) {
   var j = i;
   $http.head(allFiles[i].url).then(function(response) {
       files.push(allFiles[j]);
   }
}

Upvotes: 0

rob
rob

Reputation: 18513

You can do this with a function closure

for (var i = 0, len = allFiles.length; i < len; i++) {
    function sendRequest(index) {
        $http.head(allFiles[index].url).then(function (response) {
            files.push(allFiles[index]);
        });
    }

    sendRequest(i);
}

Upvotes: 1

Related Questions