Prompt block break in for loop

I have the following code -

this.storeNameValidate = function(stores) { var deferred = $q.defer(); console.log(stores); for (storeIndex in stores) { this.nameValidate(stores[storeIndex].storeName, 3, 10) .then(function() { console.log("valid store name"); }, function() { console.log("invalid store name"); deferred.reject("invalid store name"); }) } return deferred.promise; } 

I need to disable the for loop if the nameValidate error block is called. How can i do this?

I can do something like this using a flag

 this.storeNameValidate = function(stores) { var deferred = $q.defer(); var flag = false; console.log(stores); for (storeIndex in stores) { this.nameValidate(stores[storeIndex].storeName, 3, 10) .then(function() { console.log("valid store name"); var flag = true; }, function() { var flag = false; console.log("invalid store name"); deferred.reject("invalid store name"); }) if (!flag)break; } return deferred.promise; } 

Is this their best way?

+4
source share
3 answers

You should use $ q.all with an array of promises and return a joint promise. This only promise will be rejected if one of the internal promises fails.

 this.storeNameValidate = function (stores) { var promises = Object.keys(stores).map(function(storeIndex) { return this.nameValidate(stores[storeIndex].storeName, 3, 10).then(function () { console.log("valid store name"); }, function () { return $q.reject("invalid store name"); }); }, this); return $q.all(promises); }; 

In addition, do not abuse $q.defer , you do not need it in your case. Such excessive use of it is called a deferred anti-pattern .

In addition, if the error message you are about to reject is always an “invalid repository name” (not specified in the repository), and you do not need to pre-create additional actions in the checked repositories, you can omit errors and successful callbacks too. Then the code becomes even cleaner:

 this.storeNameValidate = function (stores) { var promises = Object.keys(stores).map(function(storeIndex) { return this.nameValidate(stores[storeIndex].storeName, 3, 10); }, this); return $q.all(promises); }; 
+4
source

You misunderstand what is happening. Your for loop exits before something else happens. He just set up all the calls, and then they all started to run async. Instead, you should save (for example) a global variable called "stop" and set it to "true" if a validation error is raised. So, in a normal success handler, you can check if stop is true, and if so, do nothing else.

Indeed, there are the right ways to handle it, and you should learn a lot of examples of promises, and you will see how they do things like “reject” promises and do “when everything”, “when there is”. You will definitely want to get a clear idea of ​​what is happening with very simple examples, and it will serve you well.

+1
source

use a global variable and test it at each iteration, if it is set to true , then break from the loop:

 var isCalled = false; this.storeNameValidate = function(stores) { var deferred = $q.defer(); console.log(stores); for (storeIndex in stores) { if(isCalled){break;} // break if the callback invoked this.nameValidate(stores[storeIndex].storeName, 3, 10) .then(function() { console.log("valid store name"); isCalled = true; }, function() { console.log("invalid store name"); deferred.reject("invalid store name"); isCalled = true; }) } return deferred.promise; } 
0
source

All Articles