在for循环中中断promise块

时间:2015-08-04 06:17:58

标签: javascript angularjs angular-promise

我有以下代码 -

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;
}

如果调用nameValidate错误块,我需要断开for循环。我怎样才能做到这一点 ?

我可以使用标记

来做到这一点
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;
}

他们有更好的方法吗?

3 个答案:

答案 0 :(得分:4)

您应该使用$q.all一组承诺并返回组合承诺。如果其中一个内部承诺失败,那么这个承诺就会拒绝。

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);

};

此外,不要滥用$q.defer你不需要它。这种冗余使用称为deferred anti-pattern

此外,如果您要拒绝的错误消息始终是"无效的商店名称" (不是特定于商店)并且您不需要在经过验证的商店上执行其他操作,您也可以一起省略错误和成功回调。然后代码将变得更加清洁:

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);

};

答案 1 :(得分:1)

你误解了发生的事情。你的for循环在其他任何事情发生之前退出。它只是设置了所有的调用,然后它们都开始运行异步。你应该做的是保持(例如)一个名为“stop”的全局变量,并在调用validate错误时将其设置为“true”。那么在正常成功处理程序中,您可以检查stop是否为true,如果是,则不要执行任何其他操作。

真的,有正确的方法来处理它,你应该研究许多承诺的例子,你会看到他们如何做“拒绝”承诺,并做“当所有”,“什么时候”。您肯定希望通过非常简单的示例清楚地了解正在发生的事情,它将为您提供良好的服务。

答案 2 :(得分:0)

使用全局变量并在每次迭代时测试它,如果它设置为true然后从循环中断:

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;
}