Получите прогресс & ldquo; get & rdquo; ajax request [duplicate]

Интересно, когда вам нужно передать параметры этой функции.

Код jsfiddle

var obj = {method:function(p1,p2,p3){console.log("method:",arguments)}}

var str = "method('p1', 'p2', 'p3');"

var match = str.match(/^\s*(\S+)\((.*)\);\s*$/);

var func = match[1]
var parameters = match[2].split(',');
for(var i = 0; i < parameters.length; ++i) {
  // clean up param begninning
    parameters[i] = parameters[i].replace(/^\s*['"]?/,'');
  // clean up param end
  parameters[i] = parameters[i].replace(/['"]?\s*$/,'');
}

obj[func](parameters); // sends parameters as array
obj[func].apply(this, parameters); // sends parameters as individual values

84
задан guari 1 October 2013 в 23:21
поделиться

5 ответов

Я пробовал три разных способа перехвата конструкции объекта Ajax:

  1. Моя первая попытка использовала xhrFields, но это разрешает только один прослушиватель, присоединяется только к загрузке (не загружать), и требует того, что кажется ненужным копированием и вставкой.
  2. Моя вторая попытка приложила функцию progress к возвращенному обещанию, но мне пришлось поддерживать собственный массив обработчиков. Я не мог найти хороший объект для прикрепления обработчиков, потому что в одном месте я мог бы получить доступ к XHR, а другой у меня был бы доступ к jQuery XHR, но у меня никогда не было доступа к отложенному объекту (только его обещание).
  3. Моя третья попытка дала мне прямой доступ к XHR для привязки обработчиков, но снова потребовала много кода для копирования и вставки.
  4. Я завернул свою третью попытку и заменил jQuery на ajax своим. Единственный потенциальный недостаток - вы больше не можете использовать свою собственную настройку xhr(). Вы можете разрешить это, проверив, есть ли функция options.xhr.

На самом деле я нахожу свою функцию promise.progress xhrProgress, поэтому я могу ее легко найти позже. Возможно, вы захотите назвать это чем-то другим, чтобы отделить слушателей загрузки и загрузки. Надеюсь, это поможет кому-то, даже если оригинальный плакат уже получил то, что ему было нужно.

(function extend_jQuery_ajax_with_progress( window, jQuery, undefined ) {
    var $originalAjax = jQuery.ajax;

    jQuery.ajax = function (url, options) {
        if (typeof(url) === 'object') {
            options = url;
            url = undefined;
        }
        options = options || {};

        // Instantiate our own.
        var xmlHttpReq = $.ajaxSettings.xhr();

        // Make it use our own.
        options.xhr = function () {
            return(xmlHttpReq);
        };

        var $newDeferred = $.Deferred();
        var $oldPromise = $originalAjax(url, options)
            .done(function done_wrapper( response, text_status, jqXHR) {
                return($newDeferred.resolveWith(this, arguments));
            })
            .fail(function fail_wrapper(jqXHR, text_status, error) {
                return($newDeferred.rejectWith( this, arguments));
            })
            .progress(function progress_wrapper() {
                window.console.warn("Whoa, jQuery started actually using deferred progress to report Ajax progress!");
                return($newDeferred.notifyWith( this, arguments));
            });

        var $newPromise = $newDeferred.promise();

        // Extend our own.
        $newPromise.progress = function (handler) {
            // Download progress
            xmlHttpReq.addEventListener('progress', function download_progress(evt) {
                // window.console.debug( "download_progress", evt );
                handler.apply(this, [evt]);
            }, false);

            // Upload progress
            xmlHttpReq.upload.addEventListener('progress', function upload_progress(evt) {
                // window.console.debug( "upload_progress", evt );
                handler.apply(this, [evt]);
            }, false);

            return(this);
        };

        return($newPromise);
    };
})(window, jQuery);
4
ответ дан Flo-Schield-Bobby 21 August 2018 в 23:24
поделиться

jQuery имеет функцию AjaxSetup() , которая позволяет регистрировать глобальные обработчики ajax, такие как beforeSend и complete для всех вызовов ajax, а также позволяет вам обращаться к объекту xhr для достижения прогресса, который вы ищете

5
ответ дан Kevin Pei 21 August 2018 в 23:24
поделиться
  • 1
    Спасибо за ссылку. Можете ли вы включить пример в свой ответ? – Michael Scheper 11 May 2015 в 23:51
  • 2
    $ .ajaxSetup ({xhr: function () {console.log ('setup XHR ...');}}); – Flo-Schield-Bobby 17 May 2015 в 09:17
  • 3
    И пример, который отвечает на вопрос? Боюсь, я не могу выдвинуть ответ, который заставляет меня много возиться и читать, особенно когда связанная страница ничего не говорит о прогрессе. Честно говоря, я скептически отношусь к этому, особенно с учетом предупреждения на этой странице, в котором говорится: «Примечание: глобальные функции обратного вызова должны быть установлены с их соответствующими глобальными методами обработчика событий Ajax: .ajaxStart(), .ajaxStop(), .ajaxComplete(), .ajaxError(), .ajaxSuccess(), .ajaxSend() - больше, чем внутри объекта options для $.ajaxSetup(). ' & Lt; [д0] api.jquery.com/jQuery.ajaxSetup/#entry-longdesc> ; – Michael Scheper 18 August 2015 в 16:01

Что-то вроде этого для $.ajax (только HTML5):

$.ajax({
    xhr: function() {
        var xhr = new window.XMLHttpRequest();
        xhr.upload.addEventListener("progress", function(evt) {
            if (evt.lengthComputable) {
                var percentComplete = evt.loaded / evt.total;
                //Do something with upload progress here
            }
       }, false);

       xhr.addEventListener("progress", function(evt) {
           if (evt.lengthComputable) {
               var percentComplete = evt.loaded / evt.total;
               //Do something with download progress
           }
       }, false);

       return xhr;
    },
    type: 'POST',
    url: "/",
    data: {},
    success: function(data){
        //Do something on success
    }
});
123
ответ дан mattytommo 21 August 2018 в 23:24
поделиться
  • 1
    Выглядит многообещающе, но как это может работать? Весь конвейер состоит из трех шагов - отправки запроса, обработки запроса в бэкэнд для генерации некоторых данных и возврата его обратно. Как клиентская сторона может знать, что делается в бэкэнд, и сколько времени потребуется, чтобы он мог рассчитать прогресс? – SexyBeast 30 April 2017 в 21:11
  • 2
    Заголовок ответа HTTP сообщает нам, сколько байтов ожидать, этот прогресс просто подсчитывает, сколько байтов было получено до сих пор. Он останется на нуле до тех пор, пока HTTP-ответ не будет отправлен – J. Allen 10 August 2017 в 21:10

jQuery уже выполнил обещания, поэтому лучше использовать эту технологию, а не переводить логику событий в параметр options. Я создал плагин jQuery, который добавляет перспективы прогресса, и теперь он прост в использовании, как и другие обещания:

$.ajax(url)
  .progress(function(){
    /* do some actions */
  })
  .progressUpload(function(){
    /* do something on uploading */
  });

Проверьте это на github

32
ответ дан shilch 21 August 2018 в 23:24
поделиться
  • 1
    Мне понравилось то, как вы используете фабрику IFI. Я не знал эту технику! – CodeArtist 25 November 2015 в 21:43
  • 2
    В настоящее время это лучшее решение, предлагаемое здесь. – atomless 27 November 2015 в 12:00
  • 3
    Рабочее и элегантное решение, но вы можете быть в курсе, что он может сломать существующий код, поскольку он разбивает все вызовы на устаревшие .success и .error. Он также удаляет все нестандартные атрибуты, установленные вами на объекте jqXHR. Он не обеспечивает также контекст в "этот" для обратного вызова uploadProgress (возможно, то же самое для прогресса, но не тестировалось), как это делается для всех стандартных обещаний для jqXHR. Поэтому вам нужно будет передать контекст в закрытии. – frank 13 March 2016 в 23:07
  • 4
    Я получаю ошибку: TypeError: $.ajax(...).progress(...).progressUpload is not a function .... В чем проблема? – Universal Grasp 26 June 2016 в 13:04
  • 5
    @UniversalGrasp привет, пожалуйста, откройте проблему в github и предоставьте информацию о том, что вы сделали. Эта библиотека не обновлялась на протяжении веков :) может быть, что-то изменилось в самом jQuery – likerRr 27 June 2016 в 07:00

http://www.htmlgoodies.com/beyond/php/show-progress-report-for-long-running-php-scripts.html

Я был поиск аналогичного решения и обнаружение этого использования полностью.

var es;

function startTask() {
    es = new EventSource('yourphpfile.php');

//a message is received
es.addEventListener('message', function(e) {
    var result = JSON.parse( e.data );

    console.log(result.message);       

    if(e.lastEventId == 'CLOSE') {
        console.log('closed');
        es.close();
        var pBar = document.getElementById('progressor');
        pBar.value = pBar.max; //max out the progress bar
    }
    else {

        console.log(response); //your progress bar action
    }
});

es.addEventListener('error', function(e) {
    console.log('error');
    es.close();
});

}

и ваши серверные выходы

header('Content-Type: text/event-stream');
// recommended to prevent caching of event data.
header('Cache-Control: no-cache'); 

function send_message($id, $message, $progress) {
    $d = array('message' => $message , 'progress' => $progress); //prepare json

    echo "id: $id" . PHP_EOL;
    echo "data: " . json_encode($d) . PHP_EOL;
    echo PHP_EOL;

   ob_flush();
   flush();
}


//LONG RUNNING TASK
 for($i = 1; $i <= 10; $i++) {
    send_message($i, 'on iteration ' . $i . ' of 10' , $i*10); 

    sleep(1);
 }

send_message('CLOSE', 'Process complete');
-3
ответ дан Sri Nair 21 August 2018 в 23:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: