我正致力于处理数据。我设置了一个按setInterval
每隔5ms调用一次的工作函数。我正在计算函数运行所需的时间,为0到1毫秒。我也在计算实际调用函数的速度和大约80ms。
我的问题是,如果只需要1ms来运行该函数,并且我每5ms调用它一次,为什么每80ms调用一次?
我确实有第二个worker函数根据处理函数正在执行的当前数据更新画布,但它在自己的setInterval中运行。
这些数字是在Chrome中拍摄的。我已经在Opera,Safari,FF3和FF4中进行了测试,但问题是相同的,尽管调用时间不同。 (这一切都在Mac上)
我知道此代码尚未在IE中工作。我知道部分内容很难看。我还没有开始清理代码......第77到84行是setInterval
次调用。
您可以看到一个有效的例子here。
(function ($) {
var methods = {
init: function (options) {
return this.each(function () {
var $this = $(this);
$this.addClass('ansiScreen');
var data = $this.data('ansi');
if (!data) {
data = new Object();
data.target = $this;
data.fontheight = 16; //12, 16, 22
data.fontwidth = Math.round(data.fontheight * 0.6) - 1;
data.canvas = $('<canvas width="' + (data.fontwidth * 80) + 'px" height="' + (data.fontheight * 25) + 'px">');
$this.append(data.canvas);
data.ctx = data.canvas[0].getContext('2d');
data.ctx.font = data.fontheight + 'px Courier New';
data.processInterval = null;
data.screenInterval = null;
data.ansi = null;
data.ansiCode = null;
data.ansiPos = 0;
data.fgcolor = 'rgb(170, 170, 170)';
data.bgcolor = 'rgb(0, 0, 0)';
data.bold = false;
data.blink = false;
data.pos = [0, 0];
data.savepos = [0, 0];
data.screen = Array();
data.last = 0;
for (var i = 0; i < 25; i++) {
data.screen.push(Array());
for (var j = 0; j < 80; j++) {
data.screen[i].push([data.bgcolor, data.fgcolor, ' ']);
}
}
$this.data('ansi', data);
}
});
},
destroy: function () {
return this.each(function () {
var $this = $(this);
var data = $this.data('ansi');
// Clean up
$(window).unbind('.ansi');
data.tooltip.remove();
$this.removeData('ansi');
});
},
load: function (ansiUrl) {
return this.each(function () {
var $this = $(this);
var me = this;
$.ajax({
'url': ansiUrl,
'data': 'text',
beforeSend: function (jqXHR, settings) {
jqXHR.overrideMimeType('text/plain; charset=x-user-defined');
},
success: function(ansiData) {
var data = $this.data('ansi');
if (data.processInterval != null) {
clearInterval(data.processInterval);
clearInterval(data.screenInterval);
}
data.ansi = ansiData;
data.ansiPos = 0;
data.fgcolor = 'rgb(170, 170, 170)';
data.bgcolor = 'rgb(0, 0, 0)';
data.bold = false;
data.blink = false;
data.pos = [0, 0];
data.savepos = [0, 0];
var interval = setInterval(function () {
processAnsi.call(me);
}, 5);
data.processInterval = interval;
interval = setInterval(function () {
updateDisplay.call(me);
}, 30);
data.screenInterval = interval;
$this.data('ansi', data);
updateDisplay.call(me);
}
});
});
}
};
$.fn.ansi = function (method) {
// Method calling logic
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.ansi');
}
};
// Process a byte from teh ansi data
function processAnsi() {
var start = new Date().getTime();
var $this = $(this);
var data = $this.data('ansi');
if (data.ansiPos > data.ansi.length)
{
clearInterval(data.processInterval);
clearInterval(data.screenInterval);
return;
}
var code = data.ansi.charCodeAt(data.ansiPos) & 0xff;
var char = data.ansi[data.ansiPos];
data.ansiPos += 1;
var now = new Date().getTime();
$this.data('ansi', data);
if (code < 33 || code > 126)
{
switch (code)
{
case 0: char = ''; break;
case 10: char = ''; cursorStartOfLine.call(this); break;
case 13: char = ''; cursorDown.call(this, 1); break;
case 27: char = ansiCode.call(this); break;
case 32: char = ' '; break;
case 176: char = '\u2591'; break;
case 177: char = '\u2592'; break;
case 178: char = '\u2593'; break;
case 179: char = '\u2502'; break;
case 185: char = '\u2563'; break;
case 186: char = '\u2551'; break;
case 187: char = '\u2557'; break;
case 188: char = '\u255D'; break;
case 191: char = '\u2510'; break;
case 192: char = '\u2514'; break;
case 193: char = '\u2534'; break;
case 194: char = '\u252C'; break;
case 195: char = '\u251C'; break;
case 196: char = '\u2500'; break;
case 197: char = '\u253C'; break;
case 180: char = '\u2524'; break;
case 200: char = '\u255A'; break;
case 201: char = '\u2554'; break;
case 204: char = '\u2560'; break;
case 205: char = '\u2550'; break;
case 215: char = '\u256B'; break;
case 217: char = '\u2518'; break;
case 218: char = '\u250C'; break;
case 219: char = '\u2588'; break;
case 220: char = '\u2584'; break;
case 221: char = '\u258C'; break;
case 222: char = '\u2590'; break;
case 223: char = '\u2580'; break;
case 250: char = '\u2022'; break;
case 254: char = '\u25a0'; break;
default: char = ''; var s = String.fromCharCode(code); break;
}
}
if (char === undefined) {
char = '[' + char + ']';
}
if (char != '') {
putCharacter.call(this, char);
}
var end = new Date().getTime();
$('#processTime').html('Requested Speed: 5ms, Process Speed: ' + (now-data.last) + 'ms, Process Time: ' + (end-start) + 'ms, Process Position: ' + data.ansiPos + ' of ' + data.ansi.length);
data = $this.data('ansi');
data.last = now;
$this.data('ansi', data);
}
function ansiCode() {
var $this = $(this);
var data = $this.data('ansi');
if (data.ansiPos > data.ansi.length)
return '-';
var valid = /^[0-9;HABCDRsuJKmh]$/;
var end = /^[HABCDRsuJKmh]$/;
var char = data.ansi[data.ansiPos];
var escape = '';
if (char == '[')
{
var stop = false;
do {
data.ansiPos += 1;
var char = data.ansi[data.ansiPos];
escape += char;
stop = end.test(char);
} while (valid.test(char) && !stop)
data.ansiPos += 1;
}
switch(escape[escape.length - 1])
{
case 'J':
if (escape == '2J') {
clearDisplay.call(this);
}
break;
case 'A':
var lines = parseInt(escape.substring(0, escape.length - 1));
if (isNaN(lines)) { lines = 1; }
data.pos[1] -= lines;
if (data.pos[1] < 0) { data.pos[1] = 0; }
break;
case 'B':
var lines = parseInt(escape.substring(0, escape.length - 1));
if (isNaN(lines)) { lines = 1; }
cursorDown.call(this, lines);
break;
case 'C':
var spaces = parseInt(escape.substring(0, escape.length - 1));
if (isNaN(spaces)) { spaces = 1; }
cursorForward.call(this, spaces);
break;
case 'D':
var lines = parseInt(escape.substring(0, escape.length - 1));
if (isNaN(lines)) { lines = 1; }
data.pos[0] -= lines;
if (data.pos[0] < 0) { data.pos[0] = 0; }
break;
case 'H':
var codes = escape.substring(0, escape.length - 1).split(';');
if (isNaN(codes[0])) { codes[0] = 1; }
if (isNaN(codes[1])) { codes[1] = 1; }
data.pos[0] = codes[1] - 1;
data.pos[1] = codes[0] - 1;
break;
case 's':
data.savepos[0] = data.pos[0];
data.savepos[1] = data.pos[1];
break;
case 'u':
data.pos[0] = data.savepos[0];
data.pos[1] = data.savepos[1];
break;
case 'm':
var codes = escape.substring(0, escape.length - 1).split(';');
for (var i=0; i < codes.length; i++) {
var code = codes[i];
switch (code) {
case '0':
data.bold = false;
data.blink = false;
data.fgcolor = 'rgb(170, 170, 170)';
data.bgcolor = 'rgb(0, 0, 0)';
break;
case '1':
data.bold = true;
break;
case '5':
data.blink = true;
break;
case '30':
data.fgcolor = !data.bold ? 'rgb(0, 0, 0)' : 'rgb(85, 85, 85)';
break;
case '31':
data.fgcolor = !data.bold ? 'rgb(170, 0, 0)' : 'rgb(255, 85, 85)';
break;
case '32':
data.fgcolor = !data.bold ? 'rgb(0, 170, 0)' : 'rgb(85, 255, 85)';
break;
case '33':
data.fgcolor = !data.bold ? 'rgb(170, 85, 0)' : 'rgb(255, 255, 0)';
break;
case '34':
data.fgcolor = !data.bold ? 'rgb(0, 0, 170)' : 'rgb(85, 85, 255)';
break;
case '35':
data.fgcolor = !data.bold ? 'rgb(170, 0, 170)' : 'rgb(255, 85, 255)';
break;
case '36':
data.fgcolor = !data.bold ? 'rgb(0, 170, 170)' : 'rgb(85, 255, 255)';
break;
case '37':
data.fgcolor = !data.bold ? 'rgb(170, 170, 170)' : 'rgb(255, 255, 255)';
break;
case '40':
data.bgcolor = !data.bold ? 'rgb(0, 0, 0)' : 'rgb(85, 85, 85)';
break;
case '41':
data.bgcolor = !data.bold ? 'rgb(170, 0, 0)' : 'rgb(255, 85, 85)';
break;
case '42':
data.bgcolor = !data.bold ? 'rgb(0, 170, 0)' : 'rgb(85, 255, 85)';
break;
case '43':
data.bgcolor = !data.bold ? 'rgb(170, 85, 0)' : 'rgb(255, 255, 0)';
break;
case '44':
data.bgcolor = !data.bold ? 'rgb(0, 0, 170)' : 'rgb(85, 85, 255)';
break;
case '45':
data.bgcolor = !data.bold ? 'rgb(170, 0, 170)' : 'rgb(255, 85, 255)';
break;
case '46':
data.bgcolor = !data.bold ? 'rgb(0, 170, 170)' : 'rgb(85, 255, 255)';
break;
case '47':
data.bgcolor = !data.bold ? 'rgb(170, 170, 170)' : 'rgb(255, 255, 255)';
break;
default:
$('#debug').html($('#debug').html() + '<br>Unknown Attribute: ' + code);
break;
}
}
break;
default:
$('#debug').html($('#debug').html() + '<br>' + escape);
break;
}
$this.data('ansi', data);
return '';
}
// Move the cursor position up a number of lines
function cursorStartOfLine(lines) {
var $this = $(this);
var data = $this.data('ansi');
data.pos[0] = 0;
$this.data('ansi', data);
}
// Move the cursor position up a number of lines
function cursorDown(lines) {
var $this = $(this);
var data = $this.data('ansi');
data.pos[1] += lines;
if (data.pos[1] > data.screen.length - 1) {
data.pos[1] = data.screen.length - 1;
for (var i = 0, length1 = data.screen.length - 1; i < length1; ++i) {
var a = data.screen[i]; // cache object
var b = data.screen[i+1]; // cache object
for (var j = 0, length2 = a.length; j < length2; ++j) {
a[j] = b[j];
}
}
for (var j = 0, length2 = a.length; j < length2; ++j) {
data.screen[data.screen.length-1][j] = ['#000000', '#ffffff', ' '];
}
}
$this.data('ansi', data);
}
// Move the cursor position back a number of columns
function cursorBack(cols) {
var $this = $(this);
var data = $this.data('ansi');
data.pos[0] -= cols;
if (data.pos[0] < 0) { data.pos[0] = 0; }
$this.data('ansi', data);
}
// Move the cursor position forward a number of columns
function cursorForward(cols) {
var $this = $(this);
var data = $this.data('ansi');
data.pos[0] += cols;
if (data.pos[0] > data.screen[0].length - 1) {
//data.pos[0] = data.screen[0].length - 1;
data.pos[0] = 0;
cursorDown.call(this,1);
}
$this.data('ansi', data);
}
// Puts a character on screen
function putCharacter(character) {
var $this = $(this);
var data = $this.data('ansi');
var style = 'background-color:' + data.bgcolor+';';
style += 'color:' + data.fgcolor+';';
data.screen[data.pos[1]][data.pos[0]] = [data.bgcolor, data.fgcolor, character, data.blink];
$this.data('ansi', data);
// Move forward 1 character
cursorForward.call(this, 1);
}
// Clear the screen
function clearDisplay() {
var $this = $(this);
var data = $this.data('ansi');
for (var i = 0; i < data.screen.length; i++) {
for (var j = 0; j < data.screen[i].length; j++) {
data.screen[i][j] = [data.bgcolor, data.fgcolor, ' ', data.blink];
}
}
data.pos = [0, 0];
$this.data('ansi', data);
}
// Update the container with the current screen
function updateDisplay() {
var start = new Date().getTime();
var $this = $(this);
var data = $this.data('ansi');
for (var i = 0, length1 = data.screen.length; i < length1; ++i) {
var a = data.screen[i]; // cache object
for (var j = 0, length2 = a.length; j < length2; ++j) {
data.ctx.fillStyle = a[j][0];
data.ctx.fillRect (data.fontwidth * j, data.fontheight * i, data.fontwidth, data.fontheight);
data.ctx.fillStyle = a[j][1];
data.ctx.textBaseline = "top";
data.ctx.fillText(a[j][2], data.fontwidth * j, data.fontheight * i);
}
}
var end = new Date().getTime();
$('#frameTime').html('Frame Draw Time: ' + (end-start));
}
})(jQuery);
答案 0 :(得分:1)
还要记住,不同的浏览器有不同的最小间隔。将间隔设置为5ms可能会触发某些浏览器的最小间隔检查。 此外,运行的计时器越多,浏览器返回队列开始的时间就越长
答案 1 :(得分:0)
Javascript是单线程的,因此使用setInterval调用的第二个函数会延迟第一个函数。