0

How to stop a function while all async call was done ? I have a foreach on a list who increment a var trough a async call or not (with if condition)

My code :

$scope.updateDureePeriodeList = function () {

        var mttLoyer = 0

        angular.forEach($scope.articleListDuree, function (value, key) {
            if (value.selected) {
                if (value.bOption) {
                    $scope.getTauxDevisRevOption(value.prixArt * value.qttArt).then(function (taux) {
                        mttLoyer += value.prixArt * value.qttArt * taux / 100;
                    })
                }
                else
                    mttLoyer += value.prixArt * value.qttArt * $scope.DureeEdit.taux / 100;
            }

        });

        $scope.DureeEdit.periodeList = new Array();
        $scope.DureeEdit.periodeList.push({
            'numPeriode': 1,
            'mttLoyer': parseFloat(mttLoyer).toFixed(2),
        });
}

Problem: getTauxDevisRevOption is async and when I go in it, my function dont stop so it do the $scope.DureeEdit.periodeList.push at the end before mttLoyer was increment in the .then() of the async call...

2
  • 2
    search how to handle async operations in javascript Commented Jul 25, 2017 at 9:23
  • I have done my search and found answers to handle async with promises (that what i do when i call getTauxDevisRevOption), but in this case im in a foreach that make me blocked and I dont found answers cause i cant do all the code in the .then() cause i need to finish my loop before call what i do in the end of the function:/ Commented Jul 25, 2017 at 9:36

2 Answers 2

1

what follows could help you

function updateDureePeriodeList(data, defaultTaux, tauxLoader) {

  return Promise
    .all(
      Object
        .keys(data)
        .reduce((res, key) => {
          const value = data[key];

          if(value.selected) {
            const op = Promise
              .resolve(value.bOption ? tauxLoader(value.prixArt * value.qttArt) : defaultTaux)
              .then(taux => (value.prixArt * value.qttArt * taux / 100))
            ;

            res = res.concat(op);
          }

          return res;
        }, [])
    )
    .then(operations => operations.reduce((a, b) => a + b))
  ;
}

updateDureePeriodeList($scope.articleListDuree, $scope.DureeEdit.taux, (...args) => $scope.getTauxDevisRevOption(...args))
  .then(mttLoyer => console.log('mttLoyer', mttLoyer))
;
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks I see how you want to handle this ! But there is a same way to do it in angularJs ?
this is angularjs
It's javascript, look for $q.all and my solution for a more angular approch, btw thank you very much, your answer got me to the right way anyway !
You shouldn't couple your code to a specific framework when there is a pure and elegant ecmascript way to do it. $q and angular.forEach are apis used to support things that weren't available 7/8 years ago and are being dropped in new angular versions. Try to write your code in EcmaScript, then, bind the code to the framework... Do you really need angular to make a loop? Do you really need for q to create a deferred object? Ho do you think to migrate your code to angular 2? Last thing, pure functions help managing side effects...
In this case why $q and angular.forEach exist in the framework ? Yes you can do it in ecmascript, but in this case why we use framework at all ? I work on a project in angular and its wouldn't be migrate to angular 2 (angular 1 and 2 are way different).
0

After loosing some hair I have finaly found the solution i was asking for ! Using $q.all was the key. My working code :

$scope.updateDureePeriodeList = function () {
        var mttLoyer = 0
        var allQ = [];

        angular.forEach($scope.articleListDuree, function (value, key) {
            if (value.selected) {
                if (value.bOption) {
                    allQ.push($scope.getTauxDevisRevOption(value.prixArt * value.qttArt).then(function (taux) {
                        mttLoyer += value.prixArt * value.qttArt * taux / 100;
                    }));
                }
                else
                    mttLoyer += value.prixArt * value.qttArt * $scope.DureeEdit.taux / 100;
           }

        });

        $q.all(allQ).then(function(data){
            $scope.DureeEdit.periodeList = new Array();
            $scope.DureeEdit.periodeList.push({
                'numPeriode': 1,
                'nbrEch': nbrEch,
                'mttLoyer': parseFloat(mttLoyer).toFixed(2),
            });
        });
}

In hope this can help someone later !

9 Comments

Did you understand the order of what happen here?
With code running in debbuging mode i see clearly the order yeah so what didn't you understand if i can help ?
You should have a better look on async code execution, while a sum result won't be altered by the order of their factors, you are executing operations in a different order regarding your input data...
"a sum result won't be altered by the order of their factors" exactly so no problem here ? Sorry I don't understand what you mean..
I think you aren't on the right mood to understand. You love how you're doing stuff... You might change once your experience will grow up.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.