Break out of promise block in a for loop

半城伤御伤魂 提交于 2019-12-23 13:21:07

问题


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 break out off the for loop if the nameValidate error block is called. How can i do this ?

I can do it something like this using flagging

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 their some better way ?


回答1:


You should use $q.all with array of promises and return combined promise. This single promise will reject if one of the inner 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);

};

Also, don't abuse $q.defer you don't need it in your case. Such a redundant usage of it is known as deferred anti-pattern.

Also, if error message you are going to reject with is always "invalid store name" (not store specific) and you don't really need to preform additional actions on validated stores, you can omit error and success callbacks all together too. Then the code will become 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);

};



回答2:


You are misunderstanding what is going on. Your for loop exits way before anything else happens. It just set's up all the calls, and then they all start running async. What you should do instead is keep (for example) a global variable called "stop" and set it to "true" if the validate error is called. So then in the normal success handler, you can check if stop is true, and if so, don't do anything else.

Really, there are correct ways of handling it, and you should study many promise examples, and you'll see how they do things like "reject" promises, and do "when all", "when any". You will definitely want to get a clear picture of what's happening with very simple examples, and it will serve you well.




回答3:


use a global variable and test it every iteration, if it 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;
}


来源:https://stackoverflow.com/questions/31801982/break-out-of-promise-block-in-a-for-loop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!