我正在通过javascript和开发者控制台测试呼叫的延迟。
在JS中,只需添加开始时间变量即可完成测量,例如:
var start_execution=Math.floor( new Date().getTime() );
// - Call a URL asynchronously
element = doc.createElement("script");
element.src = request_url;
doc.getElementsByTagName("script")[0].parentNode.appendChild(element);
//In response of the call initialize end time and call function to compute latency
var end_execution=Math.floor( new Date().getTime() );
// function call to generate latency
calculateLatency();
function calculateLatency(){
var latency= end_execution-start_execution;
}
如果在浏览器的开发人员 - 控制台/网络面板中与延迟数字一致的隔离运行,该方法可以正常工作。但是在具有大量异步内容的实际网站上,JS测量的数字最多可夸大5倍。
通过js计算的一个1000毫秒延迟在网络面板中显示为200毫秒。
这种行为非常频繁,差异也各不相同。
我怀疑有某种浏览器队列可以处理异步处理,如果遇到峰值负载,请求/响应就会卡在队列中。
我正在探索的选项是Performance http://www.w3.org/TR/resource-timing,但浏览器支持仅限于此。
我正在寻找关于javascript中计算实际延迟的行为和能力的一些解释(与网络面板中显示的相同)。还建议如何有效地使用JS截止时间进行网络调用,因为在这种情况下,膨胀的值可能会导致意外行为。
为什么我要这样做:为不执行网络呼叫设置超时但是当实际延迟的原因是浏览器处理开销时,使用setTimeOut并拒绝呼叫是不公平的。
答案 0 :(得分:0)
你的建议完全正确。
JS中的几乎所有内容都是由事件驱动的(除了某些情况,例如页面解析过程)。 任何浏览器每个窗口都有单个线程用于javascript的事件,因此每个事件处理程序都会执行,并且在处理下一个事件之前,每个事件(包括传播/冒泡和默认值)都将被完全处理。
有关更多信息,请参阅this tutorial
关于有效使用事件队列的建议,有一些建议:
XMLHttpRequest
alert
对话框进行调试,因为它们可能会完全改变您的程序逻辑。答案 1 :(得分:0)
我个人会使用http://momentjs.com/来解决与时间有关的任何事情。除此之外,我还会使用持续时间插件https://github.com/jsmreese/moment-duration-format。
在jQuery手册样式中使用它
var start_execution = moment();
var end_execution = moment();
var jqxhr = $.get( "google.com",
function(data) {
end_execution = moment();
})
.done(function() {
end_execution = moment();
})
.fail(function() {
end_execution = moment();
})
.always(function() {
var ms = start_execution.diff(end_execution);
var duration = moment.duration(ms);
console.log(duration);
});
这是正确编写的,即使请求失败或超时也能正常工作。
只是为了澄清,写下来是错误的:
var start_execution = moment();
var jqxhr = $.get( "google.com",
function(data) {
//do something with the data;
});
var end_execution = moment();
var ms = start_execution.diff(end_execution);
var duration = moment.duration(ms);
console.log(duration);
因为它只测量jQuery创建请求初始化所花费的时间,所以很可能end_execution在实际请求该资产/ url之前发送。
使用Angular,您可以编写httpInterceptorService,它可以记录事件发生的时间。
var HttpCallsApp = angular.module("HttpCallsApp", []);
HttpCallsApp.config(function ($provide, $httpProvider) {
$provide.factory("MyHttpInterceptor", function ($q) {
var log = ApplicationNamespace.Util.logger;
return {
request: function (config) {
log.info("Ajax %s request [%s] initialized", config.method, config.url);
return config || $q.when(config);
},
response: function (response) {
log.info("Ajax %s response [%s] compleated : %s ( %s )",
response.config.method, response.config.url, response.status, response.statusText);
return response || $q.when(response);
},
requestError: function (rejection) {
log.info(rejection);
// Return the promise rejection.
return $q.reject(rejection);
},
responseError: function (rejection) {
log.info(rejection);
// Return the promise rejection.
return $q.reject(rejection);
}
};
});
$httpProvider.interceptors.push("MyHttpInterceptor");
});
在angular case应用程序命名空间中包含我在app config中使用logEnhancerProvider.datetimePattern = "HH:mm:ss.SSS";
设置的应用程序范围记录器实例时间戳。从代码质量的角度来看,角度大小更好,但我不想详细介绍 - 不是你不能在jQuery中编写相同的东西,但它不是你的默认选项。
您应该看到类似的内容:
如果你不相信你的webbrowser或javascript用完浏览器 - 在flash,.net,java等程序中。您仍然可以获得请求时间。在这种情况下,您监控发送的数据包。
作为个人喜好,我更改了完成的时间戳格式。
而不是使用datetime,其中毫秒可能因系统因素而异,您可以使用 console.time()和 console.timeEnd()(旧版本中不存在) IE)。如果你可以使用performance.now更好,但它有自己的问题。这就是为什么我更喜欢使用 momentjs 。
如果您想要在传统的“浏览器”中准确地执行此操作,那么至少在Google中,他们使用了以下方法:您可以添加一个可以准确执行此操作的Flash组件。如果你记录很多,这会带来其他问题,例如数据管道限制,但是它们更容易解决,然后创建对旧版IE的支持。