我今天正在学习角度拦截器。我做了一些样本以更好地理解这个概念。这是一个小样本。
var app = angular.module("myApp", []);
app.factory("timestampMaker", [
function() {
var timestampMaker = {
request: function(config) {
console.log(config);
config.requestTimestamp = new Date().getTime();
return config;
},
response: function(response) {
response.config.responseTimestamp = new Date().getTime();
return response;
}
};
return timestampMaker;
}
]);
app.config(['$httpProvider',
function($httpProvider) {
$httpProvider.interceptors.push('timestampMaker');
}
]);
app.run(function($http) {
$http.get('https://api.github.com/users/naorye/repos').then(function(response) {
console.log(response);
var time = response.config.responseTimestamp - response.config.requestTimestamp;
console.log("The request took" + (time / 1000) + "seconds")
});
});

<html ng-app="myApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
</html>
&#13;
当我在请求函数中执行console.log(config)
时,这是控制台上的输出。
我没有得到responseTimestamp
如何出现在请求的配置对象中,其中定义了内部响应函数
答案 0 :(得分:0)
注意我使用了1.2.x的源代码,这是问题中添加的。
$httpProvider
是一个为您提供$http
服务的提供商。
作为提供者,在配置时公开一个公共数组 - 在那里你只需添加你希望在响应/请求中注入的服务名称中的所有字符串。
这就是你在这里做的事情
app.config(['$httpProvider',
function($httpProvider) {
$httpProvider.interceptors.push('timestampMaker');
}
]);
并且只能在配置时完成,因为在应用程序启动之前可以配置每docs个提供程序
您可以在第159行的source code中看到公开的数组
var responseInterceptorFactories = this.responseInterceptors = [];
当您请求$http
服务时,将其注入您的服务/控制器,
$get
函数已执行。在该函数中,您的拦截器数组将被迭代,您可以在第179行的source code中看到
var reversedInterceptors = [];
forEach(responseInterceptorFactories, function(interceptorFactory, index) {
var responseFn = isString(interceptorFactory) ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory);
/**
* Response interceptors go before "around" interceptors (no real reason, just
* had to pick one.) But they are already reversed, so we can't use unshift, hence
* the splice.
*/
reversedInterceptors.splice(index, 0, {
response: function(response) {
return responseFn($q.when(response));
},
responseError: function(response) {
return responseFn($q.reject(response));
}
});
});
按照惯例,他们会颠倒顺序。你可以看到使用字符串,他们使用$injector.get
或$injector.invoke
获得对函数的引用,并使用$q.when()
我们可以将它们引入promises链,即使它们是同步代码 - 如果您不确定我对$q.when()
到目前为止,我们有一个带有函数的数组,这些函数都是有希望的(感谢$q.when()
)。当您通过$http
这样的
$http.get('https://api.github.com/users/naorye/repos').then(function(response) {
console.log(response);
var time = response.config.responseTimestamp - response.config.requestTimestamp;
console.log("The request took" + (time / 1000) + "seconds")
});
即使您拥有.get()
,也只是here所有相同功能的快捷方式
在代码中,相关部分就是这个:
首先,使用两个值创建一个链数组:一个内部函数,它对我们的目的并不重要(但它返回一个promise - 这很重要)和未定义的值。
我们对带有拦截器的数组进行迭代,并在开始时(在请求之前)添加请求拦截器并在结束时添加响应。喜欢这个
function serverRequest {
// some code
};
var chain = [serverRequest, undefined];
var promise = $q.when(config);
// apply interceptors
forEach(reversedInterceptors, function(interceptor) {
if (interceptor.request || interceptor.requestError) {
chain.unshift(interceptor.request, interceptor.requestError);
}
if (interceptor.response || interceptor.responseError) {
chain.push(interceptor.response, interceptor.responseError);
}
});
然后,让链完成(记住我们的拦截器数组充满了承诺),代码迭代它,使用.then()
添加所有这些,导致所有这些都在链中执行,遵循承诺链接(你可以google)
while(chain.length) {
var thenFn = chain.shift();
var rejectFn = chain.shift();
promise = promise.then(thenFn, rejectFn);
}
最后,您在success
和error
中添加的回调会添加到链的最后,并且会返回承诺
promise.success = function(fn) {
promise.then(function(response) {
fn(response.data, response.status, response.headers, config);
});
return promise;
};
promise.error = function(fn) {
promise.then(null, function(response) {
fn(response.data, response.status, response.headers, config);
});
return promise;
};
return promise;
我不确定的唯一部分是在链数组中使用undefined
<强>摘要强>
您添加服务的名称,$HttpProvider
使用$invoke
服务来获取它们,并使用$q.when()
将它们添加到承诺链中,并返回承诺。最后,添加了针对特定$http
请求的回调。