我应该如何使用 angular 中的承诺设置异步错误处理?

How should I set up asynchronous error handling with promises in angular?

目前,我的应用程序中的流程看起来像这样

function searchAsync() {
    $scope.search.inProgress = true;

    return Service.search($scope.search.parameters).$promise
        .then(function (data) {
            $scope.search.data = data;
        }).catch(function (e) {
            displayError(e);
        }).finally(function () {
            $scope.search.inProgress = false;
        });
}

function initialize() {
    var promises = [];

    promises.push(setLookupsAsync($scope.categories, LookupResource.getCategories));
    promises.push(setLookupsAsync($scope.topics, LookupResource.getTopics));
    promises.push(setLookupsAsync($scope.races, LookupResource.getRaces));
    promises.push(setLookupsAsync($scope.genders, LookupResource.getGenders));

    $q.all(promises).then(function () {
        searchAsync()
    }).catch(function (e) {
        displayError(e);
    }).finally(function () {
        $scope.page.loaded = true;
    });
}

我发现如果 searchAsync 函数内的承诺失败,则错误处理是该承诺的本地错误处理,外部调用者无法知道它是否失败。如果我需要在 $q.all 'then' 片段中的 searchAsync 调用之后访问 $scope.search.data,我将无法知道它是否由于已处理的捕获或由于没有匹配项。在使用 promises 时,有没有更简洁的方法可以设置我的错误处理?

Is there a cleaner way I can set up my error handling when working with promises?

是:不要在那里处理。

由于 searchAsync return 是一个承诺,它不应该自己处理错误(除了可选地 转换 它们同时将它们保留为错误)除非它可以有意义地将错误转换为结果(它看起来不像可以)。相反,它应该让其调用者处理错误。您当前拥有的 catch 块将错误(拒绝的承诺)转换为成功(已解决的承诺),值为 undefined。 (不只是你,这是一个常见的错误。)

要么删除 catch:

function searchAsync() {
    $scope.search.inProgress = true;

    return Service.search($scope.search.parameters).$promise
        .then(function (data) {
            $scope.search.data = data;
        }).finally(function () {
            $scope.search.inProgress = false;
        });
}

...或保留它调用 displayError 但重新抛出错误:

function searchAsync() {
    $scope.search.inProgress = true;

    return Service.search($scope.search.parameters).$promise
        .then(function (data) {
            $scope.search.data = data;
        }).catch(function (e) {
            displayError(e);
            throw e; // <=========
        }).finally(function () {
            $scope.search.inProgress = false;
        });
}

一般来说,一个函数应该处理错误return承诺链,但很少两者都处理。让错误通过链传播到顶层将错误处理留给顶层,同时选择性地让所有层都知道它们发生了。 (再说一次:您可以通过执行某些操作然后重新抛出来转换错误,或者 "tap" 它;这些都很好。静默地将失败转换为 success-with-undefined 不是。:-) )