Как избежать $compile:ошибки tpload в ответе кода состояния 401
мы разрабатываем одностраничное приложение с AngularJS и ASP.NET MVC JSON Rest API.
когда неавторизованный клиент пытается перейти к частному маршруту (например:/Foo/Главная / Шаблон) чтобы получить шаблон, он получает ответ 401 от веб-API, и наше приложение AngularJS автоматически перенаправляет его на страницу входа в систему.
мы обрабатываем 401 с $http перехватчик что-то вроде это:
if (response.status === 401) { 
        $location.path(routeToLogin);
        return $q.reject(response);
}
ввода правильных учетных данных позволяет клиенту получить шаблон.
все работает отлично, за исключением одной детали; консоль Javascript сообщает об этой ошибке:
Error: [$compile:tpload] http://errors.angularjs.org/1.3.0/$compile/tpload?p0=%Foo%2FHome%2FTemplate%2F
документация AngularJs государства-это:
описание
эта ошибка возникает, когда $compile пытается извлечь шаблон из некоторых URL и запрос неудачи.
в нашем приложении AngularJs запрос терпит неудачу, но это по дизайну, потому что ресурс есть, но он не может быть доступен (401).
должен ли я двигаться дальше и принимать такого рода ошибки на консоли или можно отключить или защитить его каким-то образом?
EDIT:
я немного отладил угловой источник, и я нашел, какая часть кода вызывает исключение.
Так как мы используем TemplateUrl в объявите наши шаблоны, мы косвенно используем функцию compileTemplateUrl что делает этот вызов:
$templateRequest($sce.getTrustedResourceUrl(templateUrl))
остается второй параметр (ignoreRequestError) of templateRequest неопределено.
ignoreRequestError (необязательно)логическое
следует ли игнорировать исключение при сбое запроса или шаблон пуст
когда наш перехватчик http, регулируя код состояния 401, отвергает обещание,  $http.залезай в $TemplateRequestProvider терпит неудачу и вызывает эту функцию:
 function handleError() {
        self.totalPendingRequests--;
        if (!ignoreRequestError) {
          throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl);
        }
        return $q.reject();
      }
я считаю, что мы не можем ничего сделать, чтобы предотвратить ошибку на консоли как TemplateUrl не позволяет установить ignoreRequestError флаг в false.
я попытался обойти отклонение в случае кода состояния 401; это исправляет ошибку на консоли, но, к сожалению, имеет побочный эффект: пустой шаблон неправильно кэшируется в TemplateCache вызывает другие проблемы.
3 ответов
после некоторого размышления я вспомнил об украшении в Angular, он отлично решил эту проблему:
app.config(['$provide', function($provide) {
  $provide.decorator('$templateRequest', ['$delegate', function($delegate) {
    var fn = $delegate;
    $delegate = function(tpl) {
      for (var key in fn) {
        $delegate[key] = fn[key];
      }
      return fn.apply(this, [tpl, true]);
    };
    return $delegate;
  }]);
}]);
вы должны быть в состоянии перехватить вызов шаблона по статусу и url-адресу.
app.config(function($httpProvider) {
  var interceptor = function($location, $log, $q) {
      function success(response) {
        // The response if complete
        $log.info(response);
        return response;
      }
      function error(response) {
        // The request if errors
        $log.error(response);
        return $q.reject(response);
      }
      return function(promise) {
        return promise.then(success, error);
      }
    }
  $httpProvider.responseInterceptors.push(interceptor);
});
Как я вижу, у вас есть два варианта:
А)
идите с перехватчиками. Однако, чтобы устранить компиляцию, вам нужно вернуть код состояния успеха внутри ошибки ответа (плохо) или перенаправить на страницу входа в систему внутри перехватчика (хорошо):
app.factory('authInterceptorService', function () {
    var interceptor = {};
    interceptor.responseError = function (rejection) {
        if (rejection.status === 401 && rejection.config.url === "home template url") {
            //BAD IDEA
            //console.log("faking home template");
            //rejection.status = 200;
            //rejection.data = "<h1>should log in to the application first</h1>";
            //GOOD IDEA
            window.location = "/login.html";
        }
        return rejection;
    }
    return interceptor;
});
и на конфигурации приложения:
app.config(['$httpProvider', function ($httpProvider) {
   $httpProvider.interceptors.push('authInterceptorService');
}
вариант b)
сделать шаблон home общедоступным. В конце концов, это должна быть просто HTML-разметка, без каких-либо разумная информация.
это решение является чисто...и, возможно, это тоже возможно.
