【问题标题】:AngularJS : Chaining promisesAngularJS:链接承诺
【发布时间】:2014-12-22 15:45:40
【问题描述】:

根据AngularJS validation and promises 的建议,我想链接确认对话框,从而一次验证几个步骤。

根据用户提供的数据,进行 API 调用以查看所有需要用户确认的内容。 对于每个需要确认的步骤,提示用户并让他们决定是否进行下一步。 如果任何步骤返回 false,则整个链应返回 false。

我已经阅读了很多关于异步 JS 和 Promise 的内容,但我不得不承认我对它还是很陌生。 如何正确链接这些以获得所有步骤的最终真/假?请注意,需要 API 调用来根据提供的信息确定需要向用户显示的所有内容,因此 fetchSomeData() 作为链中的第一个调用。

任何帮助或建议将不胜感激。

fetchSomeData = function() {
    var deferred = $q.defer();
    api.fetchData(param1, param2, param3)
        .then(function(data) {
        deferred.resolve(data.content);
    }, api.errorHandler);
    return deferred.promise;
}
// data = {condition1: false, condition2: true, condition3: true}
// display confirmation dialogs for step 2 and step 3, not step 1 

confirmStep1 = function(data) {
    if (data.condition1) {
        return confirmDialogService.popConfirm('step1').then(function(confirmed) {
            return confirmed;
        }, function() {
            return false;
        });
    } else {
        return $q.when(true);
    }
}

confirmStep2 = function(data) {
    if (data.condition2) {
        return confirmDialogService.popConfirm('step2').then(function(confirmed) {
            return confirmed;
        }, function() {
            return false;
        });
    } else {
        return $q.when(true);
    }
}

confirmStep3 = function(data) {
    if (data.condition3) {
        return confirmDialogService.popConfirm('step3').then(function(confirmed) {
            return confirmed;
        }, function() {
            return false;
        });
    } else {
        return $q.when(true);
    }
}

confirmSteps = function() {
    return fetchSomeData()
        .then(confirmStep1(data))
        .then(confirmStep2(data))
        .then(confirmStep3(data));
}

confirmSteps().then(function(allConfirmed) {
    if (allConfirmed == true) {
        doSomething();
    } else {
        return;
    }
});

【问题讨论】:

  • 您是否忘记添加问题?
  • @KevinB 已编辑,感谢提醒。

标签: javascript angularjs promise angular-promise


【解决方案1】:

dfsq 开始写一个答案,但在他的祝福下删除了他的所以我正在添加我的看法:

confirmSteps = function() {
    return fetchSomeData()
        .then(confirmStep1(data))
        .then(confirmStep2(data))
        .then(confirmStep3(data));
}

这调用函数,它与setTimeout(alert("Hi"),5) 相同,您不想调用要链接它们的函数。点赞setTimeout(function(){ alert("Hi"); }, 5)

confirmSteps = function() {
    return fetchSomeData()
        .then(confirmStep1)
        .then(confirmStep2)
        .then(confirmStep3);
}

但是,这只会将data 传递给第一个承诺,并将前一个承诺的结果传递给下一个承诺,而不是将data 传递给所有三个承诺,你可以通过净一个级别来做到这一点:

confirmSteps = function() {
    return fetchSomeData().then(function(data){
        var v1, v2;
        return confirmStep1(data).then(function(d){ 
           v1 = d;
           return confirmStep2(data);
        }).then(function(d){
           v2 = d;
           return confirmStep3(data);
        }).then(function(v3){
            return v1 && v2 && v3;
        })
    });
};

这可行,但有点笨拙,相反,您可以使用短路 - 有点像 && 仅在左侧评估错误时才评估它。此外,我们可以在一个中心位置进行所有错误处理。这将使您的代码看起来像。

confirmStep1 = function(data) {
    if (data.condition1) return $q.when(true);
    return confirmDialogService.popConfirm('step1');
};

confirmStep2 = function(data) {
    if (data.condition2) return $q.when(true);
    return confirmDialogService.popConfirm('step2');
};

confirmStep3 = function(data) {
    if (data.condition3) return $q.when(true);
    return confirmDialogService.popConfirm('step3'):
};

confirmSteps = function() {
    var data = fetchSomeData();
    return data.then(confirmStep1).then(function(soFar){ 
         if(!soFar) return false; 
         return data.then(confirmStep2); 
    }).then(function(soFar){ 
         if(!soFar) return false; 
         return data.then(confirmStep3); 
    }).catch(function(){ return false; });
};

作为一个额外的提示:

fetchSomeData = function() {
    var deferred = $q.defer();
    api.fetchData(param1, param2, param3)
        .then(function(data) {
        deferred.resolve(data.content);
    }, api.errorHandler);
    return deferred.promise;
};

可以简单地变成:

fetchSomeData = function() {
    return api.fetchData(param1, param2, param3).then(function(data) {
        return data.content;
    }, api.errorHandler);
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-12
    • 2013-09-16
    • 1970-01-01
    • 1970-01-01
    • 2014-11-25
    • 1970-01-01
    相关资源
    最近更新 更多