JQuery ajax isteğinin ilerlemesini almanın en temiz yolu nedir?


105

Düz javascript'te çok basittir: sadece geri aramayı şuraya eklemeniz gerekir: {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);

ancak JQuery ( $.get()veya $.ajax()) ile html verilerini indiren bir ajax sitesi yapıyorum ve küçük bir ilerleme çubuğuyla görüntülemek için bir isteğin ilerlemesini almanın en iyi yolunun hangisi olduğunu merak ediyordum ama merakla JQuery belgelerinde yararlı bir şey bulmak ...


4
Bu umut verici görünüyor dave-bond.com/blog/2010/01/JQuery-ajax-progress-HMTL5 html5 için
PSL

1
Ooh teşekkürler çocuklar! böylece geçersiz kılma XHR'nin ihtiyacı .. garip şey Chrome Dev Araçları ile sözde kontrol ettik ki jqXHRnesne (döndürdüğü xhr nesnenin sarıcı $.ajax()) ve buldum progress(birlikte o niteliği abort, complete, successvs.), ancak JQuery belgelerinde bu eksik: api.jquery.com/jQuery.ajax/#jqXHR
guari

3
github.com/englercj/jquery-ajax-progress Bunu kullanıyorum ve diğer cevaplarla tamamen aynı, ancak daha genel şeyler
tercih ediyorum

Yanıtlar:


138

Şunun için böyle bir şey $.ajax(yalnızca HTML5 olsa da):

$.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
Umut verici görünüyor, ancak bu nasıl işleyebilir? Tüm ardışık düzen üç adımdan oluşur: istek gönderme, bazı verileri oluşturmak için arka uçta isteği işleme ve geri döndürme. İstemci tarafı, arka uçta ne yapıldığını ve ilerlemeyi hesaplamak için ne kadar zaman alacağını nasıl bilebilir?
SexyBeast

1
HTTP yanıt başlığı bize kaç bayt bekleyeceğimizi söyler, bu ilerleme sadece şimdiye kadar kaç bayt alındığını sayar. HTTP yanıtı gerçekten gönderilinceye kadar sıfırda kalacaktır
J. Allen

2
Yalnızca POST üzerinde mi çalışıyor, GET ve diğerleri de yok mu?
Raz

43

jQuery zaten vaatleri uygulamıştır, bu nedenle bu teknolojiyi kullanmak ve olay mantığını optionsparametreye taşımamak daha iyidir . İlerleme vaadi ekleyen bir jQuery eklentisi yaptım ve şimdi diğer vaatler gibi kullanımı kolay:

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

GitHub'da kontrol edin


IFI fabrikasını kullanma şeklini beğendim. O tekniği bilmiyordum!
CodeArtist

Bu, şu anda burada önerilen en iyi çözümdür.
atomless

2
Çalışan ve zarif bir çözüm, ancak kullanımdan kaldırılan .success ve .error'a yapılan tüm çağrıları kırdığı için mevcut kodunuzu kırabileceğinin farkında olabilirsiniz. Ayrıca, bir jqXHR nesnesinde ayarladığınız tüm standart olmayan öznitelikleri de çıkarır. JqXHR için tüm standart vaatler için yapıldığı gibi, uploadProgress geri çağrısı için "bu" bağlamını da sağlamaz (ilerleme için aynı olabilir ancak test edilmemiştir). Yani bağlamı bir kapanışta aktarmanız gerekecek.
frank

4
Hata alıyorum: TypeError: $.ajax(...).progress(...).progressUpload is not a function.... Sorun nedir?
Universal Grasp

@UniversalGrasp merhaba, lütfen github'da bir sorun açın ve yaptığınız şey hakkında bilgi verin. Bu kütüphane uzun
zamandır

5

Ajax nesnesinin yapısını engellemenin üç farklı yolunu denedim:

  1. İlk denemem kullanıldı xhrFields, ancak bu yalnızca bir dinleyiciye izin veriyor, yalnızca indirme (yüklemeye değil) ilerlemesine ekliyor ve gereksiz kopyala-yapıştır gibi görünen şeyleri gerektiriyor.
  2. İkinci denemem progressdöndürülen söze bir işlev ekledi, ancak kendi işleyicilerimi korumam gerekiyordu. İşleyicileri eklemek için iyi bir nesne bulamadım çünkü bir yerden XHR'ye erişebilirim ve başka bir yerde jQuery XHR'ye erişebilirdim, ancak ertelenen nesneye hiçbir zaman erişemedim (yalnızca sözünü).
  3. Üçüncü denemem, işleyicileri eklemek için XHR'ye doğrudan erişim sağladı, ancak yine çok fazla kopyala ve yapıştır kodu gerektirdi.
  4. Üçüncü denememi tamamladım ve jQuery'leri ajaxkendi girişimimle değiştirdim . Tek potansiyel eksiklik, artık kendi xhr()ayarınızı kullanamamanızdır . options.xhrBir işlev olup olmadığını kontrol ederek buna izin verebilirsiniz .

Aslında promise.progressişlevimi çağırıyorum, xhrProgressböylece daha sonra kolayca bulabilirim. Yükleme ve indirme dinleyicilerinizi ayırmak için başka bir ad vermek isteyebilirsiniz. Umarım bu, orijinal poster ihtiyaç duyduğu şeyi zaten almış olsa bile birisine yardımcı olur.

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

Bu yüzden çözümünüzü uygulamayı denedim, ancak bu kod anlamam için biraz fazla profesyonel - bunu nasıl kullanırım? Tüm kodunuzu belgemden önce kopyaladım. Zaten yapmayı denedim $.ajax({ ... }).progress(function(evl) { console.log(evl); });ama hiçbir şey olmuyor. Bana yardım eder misiniz? :)
Patrick DaVader

JQuery'nin hangi sürümünü kullanıyorsunuz?
Flo Schild

@FloSchild, lütfen kodumu yalnızca kendi biçimlendirme tercihleriniz uğruna düzenlemeyin.
MarkMYoung

3

jQuery, tüm ajax çağrıları gibi AjaxSetup()global ajax işleyicileri kaydetmenize beforeSendve aradığınız ilerlemeyi yapmak için nesneye completeerişmenize izin veren bir işleve sahiptir xhr.


2
Bağlantı için teşekkürler. Cevabınıza bir örnek ekleyebilir misiniz?
Michael Scheper

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

7
Ve soruyu cevaplayan bir örnek? Korkarım ki, özellikle bağlantılı sayfa ilerleme hakkında hiçbir şey söylemediğinde, beni çok fazla uğraşıp okumaya bırakan bir cevaba oy veremiyorum. Küresel geri arama fonksiyonları kendi küresel Ajax olay işleyicisi yöntemleri-ile ayarlanmalıdır: Doğrusu, 'Not diyor, özellikle o sayfadaki uyarıyı göz önüne alındığında, bu konuda şüpheci .ajaxStart(), .ajaxStop(), .ajaxComplete(), .ajaxError(), .ajaxSuccess(), .ajaxSend()seçenekler dahilinde daha-ziyade için itiraz $.ajaxSetup(). ' < api.jquery.com/jQuery.ajaxSetup/#entry-longdesc >
Michael Scheper

1
Dokümanlardan : Gelecekteki Ajax istekleri için varsayılan değerleri ayarlayın. Kullanımı tavsiye edilmez.
Oyvind

-1

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

Benzer bir çözüm arıyordum ve bunu tam olarak buldum.

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

}

ve sunucu çıktılarınız

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

Bu, AJAX çağrısının değil, çalışan bir PHP betiğinin ilerlemesini gösterir.
Sinus Mackowaty

-3

Ajax İsteğinin İlerlemesini görüntülemek için aşağıdaki adımları izleyin:

  1. Html ve CSS kullanarak bir Spinner oluşturun veya Bootstrap Spinner'ı kullanın.
  2. Son kullanıcı, sonsuz döngü veya eşik sınır süresi için AJAX Verilerini talep ettiğinde Döndürücüyü görüntüleyin.
  3. Bu nedenle, AJAX İsteğinin BAŞARI / HATA sonucundan sonra, şu anda görüntülenen Döndürücüyü kaldırın ve sonuçlarınızı gösterin.

İşinizi kolaylaştırmak için, bu amaçla çarkı dinamik olarak görüntülemek ve gizlemek için JS Sınıflarını kullanmanızı tavsiye ederim.

Umarım bu yardımcı olur!


2
Bu "ilerleme kaydetme" değildir, sadece "bekleyen" bir animasyon gösterir.
Sinus Mackowaty
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.