我正在嘗試爲AngularJS(1.5.x)實現一個攔截器,它可以測量每個api調用並將它們的持續時間發送到Google Analytics。如何衡量AngularJS中的請求(XHR)持續時間?
我已經開始與一個虛擬實現這一點,只用new Date().getTime()
:
(function (angular) {
'use strict';
angular.module('MODULE')
.factory('HttpLoadingInterceptor', HttpLoadingInterceptor)
.config(HttpLoadingInterceptorConfig);
HttpLoadingInterceptor.$inject = ['$injector', '$q', 'AnalyticsService', '_'];
HttpLoadingInterceptorConfig.$inject = ['$httpProvider'];
function HttpLoadingInterceptor ($injector, $q, AnalyticsService, _) {
var REQUEST_GA_EVENT_NAME = 'REQUEST';
return {
request: request,
requestError: requestError,
response: response,
responseError: responseError
};
function request (config) {
config.requestTimestamp = now();
return config || $q.when(config);
}
function requestError (rejection) {
rejection.config.responseTimestamp = now();
trackRequest(rejection);
return $q.reject(rejection);
}
function response (response) {
response.config.responseTimestamp = now();
trackRequest(response);
return response || $q.when(response);
}
function responseError (rejection) {
rejection.config.responseTimestamp = now();
trackRequest(rejection);
return $q.reject(rejection);
}
function trackRequest (response) {
if (!_.startsWith(response.config.url, 'api')) {
return;
}
AnalyticsService.trackEvent(
REQUEST_GA_EVENT_NAME,
response.config.url,
response.status,
response.config.responseTimestamp - response.config.requestTimestamp
);
}
function now() {
return new Date().getTime();
}
}
function HttpLoadingInterceptorConfig ($httpProvider) {
$httpProvider.interceptors.push('HttpLoadingInterceptor');
}
})(window.angular);
它看起來不錯乍一看,但相比那些在Chrome中網絡選項卡收集了請求的持續時間,我注意到那些收集在我的代碼中的人總是比Chrome收集的更高(有時太多!)。
說,我便想起另一個想法,就是利用用戶導航API的,所以我改變了我的代碼:
(function (angular, performance) {
'use strict';
angular.module('MODULE')
.factory('HttpLoadingInterceptor', HttpLoadingInterceptor)
.config(HttpLoadingInterceptorConfig);
HttpLoadingInterceptor.$inject = ['$injector', '$q', 'AnalyticsService', '_'];
HttpLoadingInterceptorConfig.$inject = ['$httpProvider'];
function HttpLoadingInterceptor ($injector, $q, AnalyticsService, _) {
var REQUEST_GA_EVENT_NAME = 'REQUEST';
var measureReqCnt = 1;
return {
request: request,
requestError: requestError,
response: response,
responseError: responseError
};
function request (config) {
if (shouldMeasure(config.url)) {
measureRequest(config);
}
return config || $q.when(config);
}
function requestError (rejection) {
if (shouldMeasure(rejection.config.url)) {
trackRequest(rejection);
}
return $q.reject(rejection);
}
function response (response) {
if (shouldMeasure(response.config.url)) {
trackRequest(response);
}
return response || $q.when(response);
}
function responseError (rejection) {
if (shouldMeasure(rejection.config.url)) {
trackRequest(rejection);
}
return $q.reject(rejection);
}
function shouldMeasure (url) {
return performance && _.startsWith(url, 'api');
}
function measureRequest (config) {
config.measureName = [config.url, measureReqCnt++].join('_');
config.markStartName = [config.measureName, 'start'].join('_');
config.markEndName = [config.measureName, 'end'].join('_');
performance.mark(config.markStartName);
}
function trackRequest (response) {
performance.mark(response.config.markEndName);
performance.measure(response.config.measureName, response.config.markStartName, response.config.markEndName);
var entries = performance.getEntriesByName(response.config.measureName, 'measure');
if (entries && entries.length) {
AnalyticsService.trackEvent(
REQUEST_GA_EVENT_NAME,
response.config.url,
response.status,
entries[0].duration
);
}
}
}
function HttpLoadingInterceptorConfig ($httpProvider) {
$httpProvider.interceptors.push('HttpLoadingInterceptor');
}
})(window.angular, window.performance);
..但我再次收到那些收集不同的結果鉻甚至不是那些測量使用new Date().getTime()
我做錯了什麼?我該怎麼做對嗎?也許資源時間API? AngularJS肯定會強加一點。
我無法使用用戶導航API方法 - window.performacne.getEntries()
來查找我的請求持續時間,因爲我無法識別特定請求。每個請求的參數在那裏都不可用,而且我只有很多具有不同參數的API調用。
我應該修飾AngularJS使用的原生XHR請求嗎?
當然,我試過性能API,我得到了相同的結果==沒有有效的結果。正如我在Angular團隊確定的那樣,Angular給了我們自己的開銷,所以用這些方法衡量時間是無效的。 – mrzepinski
如果你不想在你的數字中包含任何開銷,我想你必須找到一種方法來使用'performance.getEntries()'(或[PerformanceObserver](https://developer.mozilla.org/) EN-US /文檔/網絡/ API/PerformanceObserver))。順便說一下,我不知道你的確切目標與這個測量呼叫,但你確定你不想要那種開銷?因爲,這不僅僅是框架開銷,它可能是因爲你的響應太大並且解析json需要時間。我相信這是你應該衡量和關心的事情。 – inancsevinc