簡體   English   中英

javascript計時問題

[英]javascript timing issues

我正在處理數據。 我設置了一個工人函數,即setInterval每5ms調用一次。 我正在計算該函數運行所花費的時間,從0到1ms。 我還在計算實際調用函數的速度及其大約80ms。

我的問題是,如果僅需要1毫秒即可運行該函數,並且每5毫秒調用一次,為什么每80毫秒調用一次?

我確實有第二個輔助函數,根據處理函數正在處理的當前數據來更新畫布,但是它在自己的setInterval中運行。

這些數字是在Chrome中獲取的。 我也在Opera,Safari,FF3和FF4中進行了測試,盡管調用時間不同,但問題是相同的。 (所有這些都在Mac上)

我知道此代碼在IE中尚不可用。 我知道其中的一部分很丑。.我還沒有開始清理代碼……77至84行是setInterval調用。

您可以在此處看到一個有效的示例。

(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);

還要記住,不同的瀏覽器具有不同的最小間隔。 將間隔設置為5ms可能會觸發某些瀏覽器的最小間隔檢查。 此外,您運行的計時器越多,瀏覽器返回隊列開始所花費的時間就越長

Javascript是單線程的,因此使用setInterval調用的第二個函數會延遲第一個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM