понедельник, 10 февраля 2014 г.

Running CPU Intensive JavaScript Computations in a Web Browser

Пример выполнения медленных расчетов на JavaScript в браузере с предотвращением появления окна с предложением остановить сценарий замедляющий работу веб-обозревателя:

function doSomething (callbackFunction [, additional arguments]) {
    // Initialize a few things here...
    (function startNextTimeout () {
        // Do a little bit of work here...
        if (termination condition) {
            // We are done
            callbackFunction();
        } else {
            // Process next chunk
            setTimeout(startNextTimeout, 0);
        }
    })();
}

Этот паттерн можно немного модифицировать для того, чтобы он принимал функцию, отображающую прогресс выполнения длительной операции вместо функции, сообщающей о завершении длительной операции:

function doSomething (progressFunction [, additional arguments]) {
    // Initialize a few things here...
    (function startNextTimeout () {
        // Do a little bit of work here...
        if (continuation condition) {
            // Inform the application of the progress
            progressFunction(value, total);
            // Process next chunk
            setTimeout(startNextTimeout, 0);
        }
    })();
}

Пример страницы, отображающей прогрессбар выполнения длительной операции:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <title>Running long JavaScript processes in a web browser</title>
    <style>
 
        body {
            padding:0;
            margin:1em;
        }

        #progressbar {
            position:relative;
            width:300px; height:20px;
            border:1px solid black;
            overflow:hidden;
        }

        #progressbar div {
            background:#316aC5;
            width:0; height:100%;
        }
 
    </style>
  </head>
  <body>
    <p>Sorting, please wait...</p>
    <div id="progressbar"><div></div></div>

    <script>

        (function () {

            var i, length, data, el, start;

            // Initialize a few things...
            length = 1000;
            data = [];
            el = document.getElementById('progressbar').firstChild;

            // Setup an array of random integers...
            for (i = 0; i < length; i++) {
                data[i] = Math.floor(Math.random() * length);
            }

            function sort (progressFunction) {
                i = 0;

                (function startNextTimeout () {
                    var j, value;

                    for (j = length; j > i; j--) {
                        if (data[j] < data[j - 1]) {
                            value = data[j];
                            data[j] = data[j - 1];
                            data[j - 1] = value;
                        }
                    }

                    i++;

                    progressFunction(i, length);

                    if (i < length) {
                        setTimeout(startNextTimeout, 0);
                    }

                })();
            }

            start = new Date().getTime();

            sort(function (value, total) {
                el.style.width = (100 * value / total) + "%";
                if (value >= total) {
                    alert('Total duration: ' + ((new Date().getTime() - start) / 1000) + ' seconds');
                }
            });

        })();

    </script>
  </body>
</html>

Пример последовательного выполнения задач по очереди:

function saveDocument(id){

        var tasks = [openDocument, writeText, closeDocument, updateUI];

        setTimeout(function startNextTask (){

            //execute the next task

            var task = tasks.shift();

            task(id);

            //determine if there's more

            if (tasks.length > 0) {

                setTimeout(startNextTask, 25);

             }

        }, 25);

}

Комментариев нет:

Отправить комментарий