Reputation: 5084
Just when I thought I had promises figured out, I'm stumped again. I am trying to use a recursive function to return a promise. It looks like it is working but the "then" portion never gets hit. I tried using $q.all
but that is causing me a problem with multiple calls to my Web API. Rewriting the code to use recursion seemed like the answer, but I cannot get the "then" to execute. I figure that I must be missing something simple but I can't seem to figure out just what.
Here is the call to the function:
getClusterLink(linkcodes, returnString)
.then(function () {
value.vchTextBeforeQuestionCluster = $scope.returnString;
})
Here is the recursive function:
function getClusterLink(linkcodes, returnString) {
var deferred = $q.defer();
$scope.returnString = returnString;
if (linkcount < linkcodes.length) {
contractorService.gethyperlink(linkcodes[linkcount])
.success(function (data) {
var vchUrl = data[0].vchUrl;
var end = vchUrl.length;
var docID = vchUrl.substring(vchUrl.indexOf("=") + 1, end);
var vchLinkName = data[0].vchLinkName;
var yay = '<a href="" ng-click="getDocumentByID(' + docID + ')">' + vchLinkName + '</a>';
var yCode = "|Y" + linkcodes[linkcount] + "~";
$scope.returnString = $scope.returnString.replaceAll(yCode, yay);
linkcount++;
return getClusterLink(linkcodes, $scope.returnString);
})
}
else {
deferred.resolve();
return deferred.promise;
}
};
The function itself works correctly. It hits the resolve
and the return deferred.promise
, but the "then" never fires.
Any assistance is greatly appreciated!
Upvotes: 0
Views: 425
Reputation: 5084
I figured it out. Seems the problem was that I had var deferred = $q.defer()
inside of the recursive function so it kept resetting the variable. Moving it outside of the function (like below) resolved the issue and the "then" now fires.
var thisdeferred = $q.defer();
function getClusterLink(linkcodes, returnString) {
if (linkcount < linkcodes.length) {
contractorService.gethyperlink(linkcodes[linkcount])
.success(function (data) {
var vchUrl = data[0].vchUrl;
var end = vchUrl.length;
var docID = vchUrl.substring(vchUrl.indexOf("=") + 1, end);
var vchLinkName = data[0].vchLinkName;
var yay = '<a href="" ng-click="getDocumentByID(' + docID + ')">' + vchLinkName + '</a>';
var yCode = "|Y" + linkcodes[linkcount] + "~";
$scope.returnString = $scope.returnString.replaceAll(yCode, yay);
linkcount++;
return getClusterLink(linkcodes, $scope.returnString);
})
}
else {
thisdeferred.resolve();
}
return thisdeferred.promise;
};
Upvotes: 1
Reputation: 664538
Your getClusterLink
function does not return a promise in the case where contractorService.gethyperlink
is called. I wonder you don't get an exception from that. And even if you always returned deferred.promise
, it wouldn't be resolved in that branch.
But you should not use a deferred at all here. Just use $q.resolve
, and chain onto the $http
promise that gethyperlink
returns. Notice that .success
is deprecated, and does no chaining like then
does - return
ing from that callback is pointless.
function getClusterLink(linkcodes, returnString) {
$scope.returnString = returnString;
if (linkcount < linkcodes.length) {
return contractorService.gethyperlink(linkcodes[linkcount])
// ^^^^^^
.then(function (data) {
// ^^^^^
var vchUrl = data[0].vchUrl;
var end = vchUrl.length;
var docID = vchUrl.substring(vchUrl.indexOf("=") + 1, end);
var vchLinkName = data[0].vchLinkName;
var yay = '<a href="" ng-click="getDocumentByID(' + docID + ')">' + vchLinkName + '</a>';
var yCode = "|Y" + linkcodes[linkcount] + "~";
$scope.returnString = $scope.returnString.replaceAll(yCode, yay);
linkcount++;
return getClusterLink(linkcodes, $scope.returnString);
});
} else {
return $q.resolve();
}
}
Upvotes: 1
Reputation: 3611
promise has to be returned by the function before resolve or rejecting it.
function getClusterLink(linkcodes, returnString) {
var deferred = $q.defer();
$scope.returnString = returnString;
if (linkcount < linkcodes.length) {
contractorService.gethyperlink(linkcodes[linkcount])
.success(function (data) {
var vchUrl = data[0].vchUrl;
var end = vchUrl.length;
var docID = vchUrl.substring(vchUrl.indexOf("=") + 1, end);
var vchLinkName = data[0].vchLinkName;
var yay = '<a href="" ng-click="getDocumentByID(' + docID + ')">' + vchLinkName + '</a>';
var yCode = "|Y" + linkcodes[linkcount] + "~";
$scope.returnString = $scope.returnString.replaceAll(yCode, yay);
linkcount++;
})
return getClusterLink(linkcodes, $scope.returnString);
}
else {
deferred.resolve();
}
return deferred.promise;
};
.then is implemented on promise object. So as the function is returning the promise ,.then would work fine.
You can look at this sample https://jsbin.com/daseyu/edit?html,js,console,output It works fine.
I think the problem is because you are returning getClusterLink in success. You can return in end of if loop and not in .success.
Hope this helps.
Upvotes: 1