Резервный вариант выполнения XHR2

#javascript #jquery #html

#javascript #jquery #HTML

Вопрос:

У меня есть следующий пример, который использует события выполнения в XHR2 для отображения индикатора выполнения пользователю при выполнении запроса AJAX:

 $.ajax({
    xhr: function() {

        var xhr = new window.XMLHttpRequest();

        xhr.upload.addEventListener('progress', function(evt){

            if (evt.lengthComputable) {

                var percentComplete = (evt.loaded / evt.total) * 100;

                if(percentComplete >= 100){
                    $('#loading-bar').find('.bar').css({'width': percentComplete   '%'});
                    $('#loading-bar')
                    .find('.bar')
                    .on('transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd', function() {
                        $('#loading-bar').fadeOut(function(){
                            $('#loading-bar').find('.bar').css({'width': ''});
                        });
                    });
                } else {
                    $('#loading-bar').find('.bar').css({'width': percentComplete   '%'});
                }
            }                               

        }, false);

        return xhr;

    },
    type: 'GET',
    url: 'Test.html',
    success: function (response) {


    },
    error: function (jqXHR, textStatus, errorThrown) {


    }
});
  

Однако для браузеров, которые не поддерживают XHR2, панель не будет анимироваться, и элемент loading-bar не будет удален из DOM.

Как я могу реализовать резервный вариант? Поскольку я не хочу просто отключать панель загрузки при успешном завершении, поскольку это приведет к конфликту с событиями выполнения для браузеров, которые его поддерживают.

Или, что еще лучше, возможно ли получить прогресс альтернативными средствами?

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

1. Некоторые браузеры, которые не реализуют progress api, все равно позволят вам получить доступ к заголовку .response.length и content-length заголовку после получения заголовков. Для загрузки вам не повезло, afaik.

2. Почему бы не проверить в вашей функции успеха, поддерживается ли xhr2, а если нет, то только исчезает.

3. @Bergi Я не думаю, что меня волнует ход загрузки… просто загрузка, которую я показываю в своем вопросе. У вас есть несколько примеров того, как я могу использовать альтернативные API. Спасибо.

4. Извините, если я неправильно понимаю ситуацию, но это могло бы .readyState помочь? Возможно, вы могли бы упростить панель загрузки для XHR, используя .readyState .

5. @NobleMushtak Пожалуйста, не стесняйтесь показывать пример. Спасибо.

Ответ №1:

Если это прогресс загрузки, мы можем сделать это, когда xhr.readyState >= 3 . Просто прочитайте xhr.responseText.length , а затем разделите его на parseInt(xhr.getResponseHeader('Content-Length')) (при условии, что сервер предоставляет этот заголовок, и он того же происхождения или с правильным заголовком CORS).

Если это прогресс загрузки, я не знаю ни одного способа его полизаполнения исключительно на стороне клиента. Мы можем создать идентификатор для каждого сеанса загрузки и использовать другой xhr для получения прогресса получения загрузки с сервера. Однако это требует сложной реализации на стороне сервера. Существует много таких реализаций на распространенных языках, например, для PHP или .NET. Вы можете изучить их и реализовать свои собственные.

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

1. Интересует только ход загрузки. Не могли бы вы показать простой пример того, как я могу обновить ширину индикатора выполнения на основе вашего решения? Спасибо.

2. @Cameron: xhr.onreadystatechange = function() { if (xhr.readyState >= 3) { var progress = xhr.responseText.length / parseInt(xhr.getResponseHeader('Content-Length')); } };

3. Вы должны указать это в своем ответе, а затем я проведу тест.

Ответ №2:

Попробуйте использовать .onreadystatechange() с .readyState :

 getter.onreadystatechange = function() {
    if (loading) { //If the loading element has been loaded...
        if (this.status === 200) { //If this.status is already 200...
            loading.style.width = this.readyState*25 "%"; //This sets the width of loading according to this.readyState
            if (this.readyState === 4) {
                //We hide loadingBar and do stuff when we're done.
                loadingBar.style.display = "none";
               [do stuff]
            }
        }
    }
};
  

Если вы принимаете 100 Continue статусы, вы также можете указать это в панели загрузки. То, как это происходит сейчас, на некоторое время останавливается, но затем масштабируется до 100%, когда он переходит к статусу 200 OK , и readyState свойство переходит от 2 к 4 .

Вот в чем проблема: http://jsfiddle.net/NobleMushtak/QRuU6 /