Синхронный запрос на связку файлов JavaScript. sleep () в JavaScript - PullRequest
1 голос
/ 17 февраля 2011

Я хочу разрешить моим пакетам JavaScript запрашивать (синхронные вызовы ajax) другие пакеты JavaScript:

// 2 sequential synchronous calls
framework.require('packet1'); // time1 ms
framework.require('packet2'); // time2 ms
// use packets

Эти 2 запроса будут обрабатываться в течение времени 1 + время2 миллисекунды.Так что есть еще одна идея: делать эти запросы асинхронно каждый, но гарантировать, что весь пакет запросов будет обрабатываться синхронно:

// 2 parallel asynchronous calls, synchronous in total
framework.require([
    'packet1', // time1 ms
    'packet2'  // time2 ms
]);
// use packets

Насколько я понимаю, это должно быть быстрее.Теперь давайте посмотрим на мою реализацию:

framework = {
    require_counter:0,
    require: function(arr)
    {
        framework.require_counter = arr.length;

        var success = function(data, textStatus, jqXHR)
        {
            framework.require_counter -= 1;
        }
        var error = function(jqXHR, textStatus, errorThrown)
        {
            framework.require_counter -= 1;
            // some error notification
        }

        // asynchronous calls
        for (var i = 0; i < arr_js.length; i++)
            $.ajax({
                url: arr_js[i],
                success: success,
                error: error
            });

        // wait
        while (framework.require_counter > 0)
            framework.wait();

        // finally return
    }
}

Самая хитрая часть - реализовать эту функцию wait ().JavaScript не предоставляет один;другое решение должно быть найдено.Асинхронный setTimeout () не является ответом.Это мой вопрос: как реализовать функцию wait ()?Или, может быть, есть другое общее решение?

Я попробовал этот подход: http://narayanraman.blogspot.com/2005/12/javascript-sleep-or-wait.html. Может быть, вы укажете более «лаконичное» решение без серверной зависимости.

1 Ответ

1 голос
/ 17 февраля 2011

Если вам действительно нужны синхронные запросы, вы обычно можете направить соответствующий механизм AJAX для этого. Например, в jQuery вы устанавливаете для async значение значение false. При использовании XMLHttpRequest вы передаете false в качестве третьего параметра open (именно так Раман реализует sleep в сообщении блога, на которое вы ссылаетесь). Тем не менее, SJAX, как правило, плохо, поскольку он блокирует выполнение JS в текущих браузерах. Лучше использовать стиль передачи продолжения , передав функцию для выполнения остальной части вычисления:

framework = {
    require: function(urls, done)
    {
        function success(data, textStatus, jqXHR)
        {
            //...
        }
        function error(jqXHR, textStatus, errorThrown)
        {
            //...
        }

        urls.unshift('');
        function load() {
            urls.shift();
            if (urls.length) {
                $.ajax({
                    url: urls[0],
                    // here are some continuations
                    complete: load,
                    success: success,
                    error: error
                });
            } else {
                // here's a continuation invocation
                done();
            }
        }
    }
};

Если вместо синхронности вам нужно выполнить какое-то действие, когда все данные ресурсы загружены, вы можете использовать продолжение для действия, но не для загрузки ресурсов. Вместо этого вы просто применили бы модель обработки событий, записывая завершение каждой загрузки и вызывая зависимое действие после завершения всех запросов ресурсов.

framework = {
    require: function(urls, done)
    {
        var remaining = urls.length;
        var failed=[];
        // The following implementation is vulnerable to race conditions.
        // Good thing JS isn't generally multithreaded. If (when) it is,
        // and if the browser doesn't offer some form of synchronization,
        // then Peterson's algorithm should work correctly if inefficiently.
        function success(data, textStatus, jqXHR) {
            if (!--remaining) { // critical section
                done(failed);
            }
        }
        function makeErrorHandler(url) {
            return function (jqXHR, textStatus, errorThrown) {
                failed.push(url);
                if (!--remaining) { // critical section
                    done(failed);
                }
            }
        }

        for (var i=0; i < urls.length; ++i) {
            $.ajax({
                url: urls[i],
                success: success,
                error: makeErrorHandler(urls[i])
            });
        }
    }
};
...