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


105

평범한 자바 스크립트에서는 매우 간단합니다. {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 문서에서 유용한 것을 찾는 중 ...



1
오 감사합니다! 그래서 재정의 XHR에 필요 .. 이상한 것은 내가 크롬 개발 도구와 함께 소위 검사 한 것입니다 jqXHR오브젝트 (에 의해 반환 XHR 객체의 래퍼 $.ajax())와 볼 progress(와 함께 그 안에 속성을 abort, complete, success, 등)하지만, JQuery 문서에서 이것이 누락되었습니다 : api.jquery.com/jQuery.ajax/#jqXHR
guari

3
github.com/englercj/jquery-ajax-progress 나는 이것을 사용하고 다른 답변과 상당히 동일하지만 더 일반적인 것을
선호합니다

답변:


139

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

1
유망 해 보이지만 어떻게 작동 할 수 있습니까? 전체 파이프 라인은 요청을 보내고 백엔드에서 요청을 처리하여 일부 데이터를 생성하고 다시 반환하는 세 단계로 구성됩니다. 클라이언트 측은 백엔드에서 수행되는 작업과 진행 상황을 계산하는 데 걸리는 시간을 어떻게 알 수 있습니까?
SexyBeast

1
HTTP 응답 헤더는 예상되는 바이트 수를 알려주며,이 진행 상황은 단순히 지금까지 수신 된 바이트 수를 계산하는 것입니다. HTTP 응답이 실제로 전송 될 때까지이 제로에 남아있을 것입니다
J. 알렌에게

2
POST에서만 작동하고 GET 및 기타도 얻지 못합니까?
Raz

43

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

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

github 에서 확인하세요


IFI 공장을 사용하는 방식이 마음에 들었습니다. 나는 그 기술을 몰랐다!
CodeArtist 2015

이것은 현재 여기에서 제안 된 최상의 솔루션입니다.
atomless

2
작동하고 우아한 솔루션이지만 더 이상 사용되지 않는 .success 및 .error에 대한 모든 호출을 중단하기 때문에 기존 코드가 손상 될 수 있음을 알고있을 수 있습니다. 또한 jqXHR 객체에 설정 한 모든 비표준 속성을 제거합니다. 또한 jqXHR에 대한 모든 표준 약속에 대해 수행되므로 uploadProgress 콜백에 대해 "this"에 대한 컨텍스트를 제공하지 않습니다 (진행에 대해서는 동일하지만 테스트되지는 않음). 따라서 클로저에서 컨텍스트를 전달해야합니다.
프랭크

4
오류가 발생합니다. TypeError: $.ajax(...).progress(...).progressUpload is not a function.... 무엇이 문제입니까?
Universal

@UniversalGrasp 안녕하세요, github에서 문제를 열고 수행 한 작업에 대한 정보를 제공하십시오. 이 라이브러리는 연령대에 업데이트되지 않은 : 뭔가를 할 수는 jQuery를 그 자체로 변경되었습니다
likerRr

5

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

그래서 방금 솔루션을 구현하려고 시도했지만이 코드는 이해하기에는 너무 프로 적입니다. 어떻게 사용합니까? 내 document.ready 전에 전체 코드를 복사하고 시도 $.ajax({ ... }).progress(function(evl) { console.log(evl); });했지만 아무 일도 일어나지 않습니다. 도와주세요? :)
Patrick DaVader

어떤 버전의 jQuery를 사용하고 있습니까?
Flo Schild

@FloSchild, 자신의 서식 설정을 위해 내 코드를 편집하지 마십시오.
MarkMYoung

3

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


2
링크 주셔서 감사합니다. 답변에 예를 포함 할 수 있습니까?
Michael Scheper

$ .ajaxSetup ({xhr : function () {console.log ( 'setup XHR ...');}});
Flo Schild

7
그리고 질문에 답하는 예? 나는 특히 링크 된 페이지가 진행 상황에 대해 아무것도 말하지 않을 때, 나를 많이 다루고 읽게하는 답변을 찬성 할 수 없습니다. 글로벌 콜백 함수는 각각의 글로벌 아약스 이벤트 핸들러 methods-로 설정해야합니다 : 솔직히, 나는 '주 말한다, 특히 해당 페이지의 경고를 주어, 이것에 대해 회의적 .ajaxStart(), .ajaxStop(), .ajaxComplete(), .ajaxError(), .ajaxSuccess(), .ajaxSend()옵션 내에서보다 -rather가 반대 $.ajaxSetup(). ' < api.jquery.com/jQuery.ajaxSetup/#entry-longdesc >
Michael Scheper

1
문서에서 : 향후 Ajax 요청에 대한 기본값을 설정하십시오. 사용하지 않는 것이 좋습니다.
Oyvind

-1

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 호출이 아닌 실행중인 PHP 스크립트의 진행 상황을 보여줍니다.
Sinus Mackowaty

-3

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

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

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

이게 도움이 되길 바란다!


2
그것은 "진행을 얻는 것"이 ​​아니라 단지 "대기"애니메이션을 보여주는 것입니다.
Sinus Mackowaty
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.