Thursday 20 April 2017

Angular JS - Javascript Madness

Those of you who have struggled with order in ansynchronous service calls in Angular JS will understand why I've posted the code below, for reference purposes. 

I just have to record the following as it took quite an effort to make sure two subsequent calls are made based on deferred promises with a final piece of code actually amending the results returned as part of the first promise. Hope you find it useful. 

$scope.validateDEXDeals = function(deals, arrayOfIndexes, dealResult, counter, deferred) {
        // extract the current deal's id into a variable
        var dealId = dealResult.deal.id;
        // extract the index of the current deal from the deal array 
        var index = deals.indexOf(dealResult);
       
        // call the workflow service to retrieve possible completed DEX processes
        WorkflowService.retrieveHistoricProcesses('completed', 'DEX', dealId).$promise.then(function (histResponse) {
// IF there does NOT exist a completed DEX process, splice the deal from the response
if (histResponse.data && histResponse.data.length <= 0) {
// record the index to splice
arrayOfIndexes.push(index);
// increase the counter object's value
counter.value++;
// when all the deals have been touched on, we may resolve the deferred promise.
if (counter.value == deals.length) {
deferred.resolve(arrayOfIndexes);
}

 // ELSE, leave the deal as part of the response
} else {
// increase the counter object's value
counter.value++;
// when all the deals have been touched on, we may resolve the deferred promise.
if (counter.value == deals.length) {
deferred.resolve(arrayOfIndexes);
}
}
});
        }
        
        $scope.doExtendedDocExaminationCheck = function(deals) {
        var arrayOfIndexes = [], deferred = $q.defer();
       
        // IF there are completed deals for the given production reference
if (deals) {
// setup a counter object in order to carry the correct index of the coming FOR loop.
var counter = {}
counter.value = 0;
// for each deal, go and validate whether there are DEX completed processes
for (var i=0; i<deals.length; i++) { 
var dealResult = deals[i];
// if the deal result contains a deal
if (dealResult.deal) {
// Check whether there exist completed DEX processes for the given deal
$scope.validateDEXDeals(deals, arrayOfIndexes, dealResult, counter, deferred);

} else { // otherwise increment the counter and continue with the rest of the deals.
counter.value++;
// If all deals have been visited, resolve the deferred promise
if (counter.value == deals.length) {
deferred.resolve(arrayOfIndexes);
}
}
}

} else {
// resolve the deferred promise, otherwise
deferred.resolve(arrayOfIndexes);
}
// return the deferred promise.
return deferred.promise;
        }
        
        

$scope.suggest = function(val) {
// reset deal search results on entry
$scope.dealResult = {};
// response promise from search on deal by production reference
var response;
// SPECIAL response promise to ensure synchronous execution of code on the payment of an LC
// (all options are anyway included in the special promise)
var responsePromise = $q.defer();

// if searching for a Deal with the intention to make a PAYMENT
if ($scope.case.stepCode === 'PAY') {

var _prodDesc = $rootScope.arrayFilter( $rootScope.allProducts,{"id":$scope.case.productCode},'description');
// check that the product in question is in fact a LC, as payment only applies to LCs

if (_prodDesc.indexOf('LC') >= 0) {
// Check whether there are completed deals with the given production reference (similar to other product searches)
response = DealService.dealByProdRef(val, $scope.case.productCode).$promise;

// On response of the deal search...continue to the following check
response.then(function (deals) {
// Check whether there exist completed DEX processes for the given deal
var indexesToSplicePromise = $scope.doExtendedDocExaminationCheck(deals);
//  On return of the possible indexes promise, remove the deals at the specified indexes.
indexesToSplicePromise.then(function(indexesToSplice) {
angular.forEach(indexesToSplice, function(index) {
// remove the deal at the given index
deals.splice(index, 1);
});
// resolve the SPECIAL promise on the modified deals promise
responsePromise.resolve(deals);
});
});

} else {
// search on Deal with no restrictions for any other product type, than LCs.
response = DealService.dealByProdRef(val, $scope.case.productCode).$promise;
// resolve the SPECIAL promise on the deals promise
response.then(function(data) {
responsePromise.resolve(data);
});
}
} else {
// search on Deal with no restrictions.
response = DealService.dealByProdRef(val, $scope.case.productCode).$promise;
// resolve the SPECIAL promise on the deals promise
response.then(function(data) {
responsePromise.resolve(data);
});
}
// return the SPECIAL response promise of the deal search for the type suggestion.
return responsePromise.promise;
        };