我使用角度$ http拦截器来检查ajax请求是否返回401(未经过身份验证)。 如果响应为401,则原始请求排队,显示登录表单,登录成功后,将重试排队的请求。这已经与$ http一起使用了,角度拦截器的来源是:
define('common.service.security.interceptor', ['angular'], function() {
'use strict';
angular.module('common.service.security.interceptor', ['common.service.security.retryQueue'])
.factory('securityInterceptor', [
'$injector',
'$location',
'securityRetryQueue',
function($injector, $location, securityRetryQueue) {
return function(promise) {
var $http = $injector.get('$http');
// catch the erroneous requests
return promise.then(null, function(originalResponse){
if(originalResponse.status === 401){
promise = securityRetryQueue.pushRetryFn('Unauthorized', function retryRequest(){
return $injector.get('$http')(originalResponse.config);
});
}
return promise;
});
};
}
])
// register the interceptor to the angular http service. method)
.config(['$httpProvider', function($httpProvider) {
$httpProvider.responseInterceptors.push('securityInterceptor');
}]);});
如何使用这个有角度的$ http拦截器创建breeze请求?
Breeze为文件“Breeze / Adapters / breeze.ajax.angular.js”中的angular $ http服务提供了一个包装器。所以第一个想法是告诉微风使用它:
breeze.config.initializeAdapterInstance("ajax", "angular", true);
调试angular.js,它显示breeze现在实际上使用$ http,但它不执行上面注册的拦截器。在$ http里面,有一个数组“reversedInterceptors”,它包含已注册的拦截器。我将此数组记录到控制台。如果我使用$ http,则此数组的长度为1(如预期的那样),但在使用breeze发出请求时,此数组为空。
问题是,如何在微风请求中使用这个$ http拦截器?
以下是breeze提供的breeze.ajax.angular.js的代码
define('breeze.ajax.angular.module', ['breeze', 'angular'], function (breeze) {
'use strict';
/* jshint ignore:start */
var core = breeze.core;
var httpService;
var rootScope;
var ctor = function () {
this.name = "angular";
this.defaultSettings = {};
};
ctor.prototype.initialize = function () {
var ng = core.requireLib("angular");
if (ng) {
var $injector = ng.injector(['ng']);
$injector.invoke(['$http', '$rootScope',
function (xHttp, xRootScope) {
httpService = xHttp;
rootScope = xRootScope;
}]);
}
};
ctor.prototype.setHttp = function (http) {
httpService = http;
rootScope = null; // to suppress rootScope.digest
};
ctor.prototype.ajax = function (config) {
if (!httpService) {
throw new Error("Unable to locate angular for ajax adapter");
}
var ngConfig = {
method: config.type,
url: config.url,
dataType: config.dataType,
contentType: config.contentType,
crossDomain: config.crossDomain
}
if (config.params) {
// Hack: because of the way that Angular handles writing parameters out to the url.
// so this approach takes over the url param writing completely.
// See: http://victorblog.com/2012/12/20/make-angularjs-http-service-behave-like-jquery-ajax/
var delim = (ngConfig.url.indexOf("?") >= 0) ? "&" : "?";
ngConfig.url = ngConfig.url + delim + encodeParams(config.params);
}
if (config.data) {
ngConfig.data = config.data;
}
if (!core.isEmpty(this.defaultSettings)) {
var compositeConfig = core.extend({}, this.defaultSettings);
ngConfig = core.extend(compositeConfig, ngConfig);
}
httpService(ngConfig).success(function (data, status, headers, xconfig) {
// HACK: because $http returns a server side null as a string containing "null" - this is WRONG.
if (data === "null") data = null;
var httpResponse = {
data: data,
status: status,
getHeaders: headers,
config: config
};
config.success(httpResponse);
}).error(function (data, status, headers, xconfig) {
var httpResponse = {
data: data,
status: status,
getHeaders: headers,
config: config
};
config.error(httpResponse);
});
rootScope && rootScope.$digest();
};
function encodeParams(obj) {
var query = '';
var key, subValue, innerObj;
for (var name in obj) {
var value = obj[name];
if (value instanceof Array) {
for (var i = 0; i < value.length; ++i) {
subValue = value[i];
fullSubName = name + '[' + i + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += encodeParams(innerObj) + '&';
}
} else if (value instanceof Object) {
for (var subName in value) {
subValue = value[subName];
fullSubName = name + '[' + subName + ']';
innerObj = {};
innerObj[fullSubName] = subValue;
query += encodeParams(innerObj) + '&';
}
} else if (value !== undefined) {
query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&';
}
}
return query.length ? query.substr(0, query.length - 1) : query;
}
breeze.config.registerAdapter("ajax", ctor);
breeze.config.initializeAdapterInstance("ajax", "angular", true);
/* jshint ignore:end */
});
答案 0 :(得分:6)
使用setHttp方法可以让我使用带有微风角度ajax适配器的http拦截器。在我的环境中,它看起来像这样:
(function() {
'use strict';
var serviceId = 'entityManagerFactory';
angular.module('app').factory(serviceId, ['$http', emFactory]);
function emFactory($http) {
var instance = breeze.config.initializeAdapterInstance("ajax", "angular");
instance.setHttp($http);
...
}
})();
我唯一真正找到相关信息的地方是download页面上1.4.4的发行说明。我真的不明白这是做什么的。我相信其中一个微风男人会有更好的解释。
答案 1 :(得分:4)
您必须按照@almaplayera 的说明致电setHttp($http)
。请将他标记为正确的答案。
这就是必要的原因。
默认情况下,breeze angular ajax adapter使用$ http的任何实例初始化自身。不幸的是,在加载大多数脚本时,尚未创建您的APP的$http
实例。在模块加载之前不会发生这种情况......通常在微风加载后很久就会发生。
因此,breeze不是创建一个根本不起作用的适配器,而是旋转它自己的$http
实例,并将角度ajax适配器连接到该实例。
如果你的代码没有做任何特殊的事情,这很好用。这不是最佳的;你会得到一个超过必要的$digest
周期。但它适用于大多数人,让我们承认有足够的配置噪音可以处理。
但是你正在做一些特别的事情。您正在配置一个非常具体的$http
实例,而不是微风为自己创建的实例。
所以你必须告诉微风使用你的$http
的实例......这就是你致电setHttp($http)
时会发生的事情;
感谢您的反馈,我更新了breeze documentation on ajax adapters来描述如何配置Angular应用。