Rani Radcliff Rani Radcliff - 1 month ago 9
AngularJS Question

AngularJs Promise "Then" Fires before promise is resolved

I'm having a problem with chained promises on a recursive function. My recursive function is similar to the answer found here on Stack Overflow on a similar issue. The problem is the call to the promise function is an angular.forEach. The first one returns perfectly, however when the second one runs, the "then" is hit but the response is still holding the value for the previous promise so I am getting the same data back twice. By the time the second promise is resolved, it is too late and the page has already rendered with duplicate information.

Here is my promise function:

angular.forEach(question, function(value,key){
var returnString = value.myString
var promise = getClusterLink(linkcodes, returnString)
promise.then(function (response) {
value.myString = response;
linkcount = 0;
})
})


My recursive function:

var thisdeferred = $q.defer();

function getClusterLink(linkcodes, returnString) {
contractorService.gethyperlink(linkcodes[linkcount])
.success(function (data) {
var vchUrl = data[0].vchUrl;

var yCode = "|Y" + linkcodes[linkcount] + "~";
returnString = returnString.replaceAll(yCode, vchUrl);
linkcount++;
if (linkcount < linkcodes.length) {
return getClusterLink(linkcodes, returnString);
}
else {

thisdeferred.resolve(returnString);
}
})

return thisdeferred.promise;

};


I tried putting a timeout on the deferred.resolve but I still get the same duplication it just takes longer. Any assistance is greatly appreciated!

Answer

You only have one deferred, and it's created outside the function, so the second time that function runs, your one single deferred is already resolved.

As it's recursive, you have to change it a little bit

function getClusterLink(linkcodes, returnString) {

    var thisdeferred = $q.defer();

    (function recursive(linkcodes, returnString)  {

        contractorService.gethyperlink(linkcodes[linkcount]).success(function(data) {
            var vchUrl = data[0].vchUrl;
            var yCode  = "|Y" + linkcodes[linkcount] + "~";

            returnString = returnString.replaceAll(yCode, vchUrl);

            linkcount++;

            if (linkcount < linkcodes.length) {
                return recursive(linkcodes, returnString);
            } else {
                return thisdeferred.resolve(returnString);
            }
        });

    })(linkcodes, returnString);

    return thisdeferred.promise;
};