在 Angular 中使用拦截器处理错误的通用方法

Generic way of error handling in Angular using interceptors

本文关键字:错误 处理 方法 Angular      更新时间:2023-09-26

我正在使用 Angular 1.08,因此我需要使用 responseInterceptors .

首先是代码。

译员:

app.factory('errorInterceptor', ['$q', 'NotificationService', function ($q, NotificationService) {
    return function (promise) {
        return promise.then(function (response) {
            // do something on success
            return response;
        }, function (response) {
            // do something on error
            alert('whoops.. error');
            NotificationService.setError("Error occured!");
            return $q.reject(response);
        });
    }
}]);
app.config(function ($httpProvider) {
    $httpProvider.responseInterceptors.push('errorInterceptor');
});

通知服务:

app.service("NotificationService", function () {
    var error = '';
    this.setError = function (value) {
        error = value;
    }
    this.getError = function () {
        return error;
    }
    this.hasError = function () {
        return error.length > 0;
    }
});

指令错误框:

app.directive("errorBox", function (NotificationService) {
    return {
        restrict: 'E',
        replace: true,
        template: '<div data-ng-show="hasError">{{ errorMessage }}</div>',
        link: function (scope) {
            scope.$watch(NotificationService.getError, function (newVal, oldVal) {
                if (newVal != oldVal) {
                    scope.errorMessage = newVal;
                    scope.hasError = NotificationService.hasError();
                }
            });
        }
    }
});

问题:当我在多个地方使用<error-box>时,所有这些框都会显示错误消息。这不是我的本意。我只想显示发生异常的错误框。

例如,我有一个指令,它显示交易列表。当获取事务失败时,我想显示该部分中声明的错误框。我还有一个指令,我可以在其中编辑客户。此指令还包含错误框标记。

发生的情况是,当保存客户失败时,将显示两个错误框,但是,我只希望显示客户的错误框。

有人有实现这个的想法吗?

Angular 服务是 Singleton 对象,如此处的 angular 文档中所述。 这意味着 Angular 只创建一个服务的"全局"实例,并在请求给定服务时使用相同的实例。 这意味着 Angular 只会创建 NotificationService 服务的一个实例,然后将该实例提供给 errorBox 指令的每个实例。 因此,如果一个指令更新NotificationService的错误值,那么所有<error-box指令都将获得该值。

因此,您将不得不为每种类型的错误(即TransactionNotificationCustomerNotification等)创建多个通知服务,或者向主要NotificationService添加不同的方法,以允许您仅设置特定的警报(例如NotificationService.setCustomerError()NotificationService.setTransactionError())。

这些选项都不是特别用户友好或干净,但我相信(考虑到您设置服务的方式),这是唯一的方法。

更新:考虑了一下之后,我可能会建议放弃整个NotificationService类,只使用$scope事件在发生错误时通知您的<error-box>元素:

在您的'errorInterceptor'

app.factory('errorInterceptor', ['$q', '$rootScope', function ($q, $rootScope) {
    return function (promise) {
        return promise.then(function (response) {
            // do something on success
            return response;
        }, function (response) {
            // do something on error
            alert('whoops.. error');
            var errorType = ...; // do something to determine the type of error
            switch(errorType){
                case 'TransactionError':
                    $rootScope.$emit('transaction-error', 'An error occurred!');
                    break;
                case 'CustomerError':
                    $rootScope.$emit('customer-error', 'An error occurred!');
                    break;
                ...
            }
            return $q.reject(response);
        });
    }
}]);

然后在您的errorBox指令中:

link: function (scope, element, attrs) {
        var typeOfError = attrs.errorType;
        scope.$on(typeOfError, function (newVal, oldVal) {
            if (newVal != oldVal) {
                scope.errorMessage = newVal;
            }
        });
    }

然后在您看来:

<error-box error-type="transaction-error"></error-box>
<error-box error-type="customer-error"></error-box>

这有意义吗?