如何避免401状态代码响应上的$compile:tpload错误
How to avoid $compile:tpload errors on 401 status code response
我们正在使用AngularJS和ASP.NET MVC Json Rest API开发单页应用程序。
当未经验证的客户端尝试导航到专用路由(例如:/Foo/Home/Template)以获取模板时,它会从Web API获得401响应,我们的AngularJS应用程序会自动将其重定向到登录页面。
我们正在处理带有$http的401拦截器,其内容如下:
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)。
我应该继续接受控制台上的这种错误吗?还是可以以某种方式将其静音或屏蔽?
编辑:
我对角度源进行了一点调试,发现代码的哪一部分引发了异常
由于我们使用TemplateUrl
来声明我们的模板,因此我们间接地使用了进行以下调用的函数compileTemplateUrl
:
$templateRequest($sce.getTrustedResourceUrl(templateUrl))
这使得CCD_ 4的第二参数(ignoreRequestError
)未被定义。
ignoreRequestError(可选)布尔值
当请求失败或模板为空
当我们的http拦截器(处理401状态代码)拒绝promise时,$TemplateRequestProvider
中的$http.get失败并调用以下函数:
function handleError() {
self.totalPendingRequests--;
if (!ignoreRequestError) {
throw $compileMinErr('tpload', 'Failed to load template: {0}', tpl);
}
return $q.reject();
}
我相信我们无法阻止控制台上的错误,因为TemplateUrl
不允许将ignoreRequestError
标志设置为false。
在401状态码的情况下,我试图绕过拒绝;这修复了控制台上的错误,但遗憾的是,它有一个副作用:一个空模板被错误地缓存到TemplateCache
中,导致其他问题。
经过思考,我想起了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拦截对模板的调用。
Plunker
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);
});
在我看来,您有两个选项:
选项A)
去拦截。然而,为了消除编译,您需要在响应错误(BAD)内返回成功状态代码,或者重定向到拦截器内的登录页面(Good):
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)
将主模板公开。毕竟,它应该只是html标记,没有任何合理的信息。
这个解决方案是干净的。。。也许也是可能的。
- 错误:[$compile:nonassign]表达式'未定义'与指令'内容可编辑'是不可
- 在什么情况下需要同时使用compile&链接函数的角度
- 由于$compile,Javascript(Angular)嵌套指令加载了两次
- Ember 1.10-升级错误-模板必须是一个函数.您是想调用Ember.Handlebars.compile(“..”
- $compile和ng repeat未返回正确的元素
- 未捕获错误:在未加载模板编译器的情况下,无法调用“compile”.请在调用“compile”之前加载“ember te
- 使用jade.compile编译一个jade模板,该模板是一个mixin文件或包含部分
- Angular ngRoute可以't加载模板:错误[$compile:tpload]
- Angular: Compile is not defined
- 使用 Angular.js 使用多选下拉列表时出现 [$compile:multidir] 错误
- 检测在angular中传递给$compile的字符串的最佳方法是可编译的
- 如何定义$compile服务何时在angular中完全完成编译
- Angular2 $compile directive as AngularJS 1
- 了解 AngularJS $compile函数
- 错误:[$compile:multidir] 将 md-sidenav 与控制器(角度材料)绑定时
- AngularJS:如何知道$compile何时完成
- 为什么 ngClick 在$compile后不再工作
- 在请求范围的服务中使用$compile
- 如何避免401状态代码响应上的$compile:tpload错误
- 错误:$compile:tpload未能加载模板Http状态:404