[javascript] JQuery Ajax 요청의 진행 상황을 얻는 가장 깨끗한 방법은 무엇입니까?

평범한 자바 스크립트에서는 매우 간단합니다. {XMLHTTPRequest}.onprogress

var xhr = new XMLHttpRequest();

xhr.onprogress = function(e){
    if (e.lengthComputable)
        var percent = (e.loaded / e.total) * 100;
};

xhr.open('GET', 'http://www...', true);
xhr.onreadystatechange = function() {
    ...
};
xhr.send(null);

하지만 JQuery ( $.get()또는 $.ajax())로 html 데이터를 다운로드하는 ajax 사이트를 만들고 있는데, 작은 진행률 표시 줄로 표시하기 위해 요청의 진행 상황을 얻는 가장 좋은 방법이 무엇인지 궁금합니다. JQuery 문서에서 유용한 것을 찾는 중 …



답변

다음과 같은 것 $.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
    }
});


답변

jQuery는 이미 promise를 구현 했으므로이 기술을 사용하고 이벤트 논리를 options매개 변수 로 이동하지 않는 것이 좋습니다 . 진행률 약속을 추가하는 jQuery 플러그인을 만들었고 이제 다른 약속처럼 사용하기 쉽습니다.

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

github 에서 확인하세요


답변

Ajax 객체의 구성을 가로채는 세 가지 방법을 시도했습니다.

  1. 내 첫 번째 시도는를 사용 xhrFields했지만 한 명의 리스너 만 허용하고 다운로드 (업로드 아님) 진행률에만 첨부하고 불필요한 복사 및 붙여 넣기처럼 보이는 것이 필요합니다.
  2. 두 번째 시도 progress는 반환 된 promise에 함수를 추가했지만, 고유 한 핸들러 배열을 유지해야했습니다. 한 곳에서는 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 )
    {
        xmlHttpReq.addEventListener( 'progress', function download_progress( evt )
        {
            //window.console.debug( "download_progress", evt );
            handler.apply( this, [evt]);
        }, false );
        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 );


답변

jQuery에는 모든 ajax 호출 과 AjaxSetup()같은 전역 ajax 핸들러를 등록 beforeSend하고 원하는 진행을 수행하기 위해 객체에 complete액세스 xhr할 수있는 기능이 있습니다.


답변

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


답변

Ajax 요청 진행 상황을 표시하려면 다음 단계를 따르십시오.

  1. Html 및 CSS를 사용하여 Spinner를 만들거나 Bootstrap Spinner를 사용합니다.
  2. 최종 사용자가 무한 루프 또는 임계 값 제한 시간에 대해 AJAX 데이터를 요청할 때 Spinner를 표시합니다.
  3. 따라서 AJAX 요청의 SUCCESS / ERROR 결과 후에 현재 표시된 Spinner를 제거하고 결과를 표시하십시오.

쉽게하기 위해이 목적을 위해 스피너를 동적으로 표시하고 숨기는 데 JS 클래스를 사용하는 것이 좋습니다.

이게 도움이 되길 바란다!


답변