JQuery के अजाक्स अनुरोध की प्रगति प्राप्त करने का सबसे साफ तरीका क्या है?


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

लेकिन मैं एक अजाक्स साइट कर रहा हूं जो html डेटा को JQuery ( $.get()या $.ajax()) के साथ डाउनलोड करता है और मैं सोच रहा था कि किसी अनुरोध की प्रगति को प्राप्त करने का सबसे अच्छा तरीका क्या है ताकि इसे थोड़ी प्रगति पट्टी के साथ प्रदर्शित किया जा सके लेकिन उत्सुकता से, मैं नहीं हूं JQuery प्रलेखन में उपयोगी कुछ भी खोजने ...


4
यह html5 के लिए होनहार dave-bond.com/blog/2010/01/JQuery-ajax-progress-HMTL5 लग रहा है
PSL

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
होनहार लगता है, लेकिन यह संभवतः कैसे काम कर सकता है? संपूर्ण पाइपलाइन में तीन चरण होते हैं - एक अनुरोध भेजना, बैकेंड में अनुरोध को संसाधित करना, कुछ डेटा उत्पन्न करना और इसे वापस करना। ग्राहक पक्ष संभवतः यह कैसे जान सकता है कि बैकएंड में क्या किया जा रहा है और कितना समय लगेगा कि यह प्रगति की गणना कर सकता है?
सेक्सीबीस्ट

1
HTTP प्रतिसाद हेडर हमें बताता है कि कितने बाइट्स की उम्मीद है, यह प्रगति बस गिनती कर रही है कि अब तक कितने बाइट प्राप्त हुए हैं। यह तब तक शून्य पर रहेगा जब तक कि HTTP रिस्पांस वास्तव में नहीं भेजा जाता
जे। एलन

2
क्या यह केवल POST पर काम कर रहा है, GET और अन्य को भी नहीं मिला है?
रज़

43

jQuery ने पहले ही वादे लागू कर दिए हैं, इसलिए इस तकनीक का उपयोग करना बेहतर है और घटनाओं के तर्क को optionsपैरामीटर में नहीं ले जाना चाहिए । मैंने एक jQuery प्लगइन बनाया जो प्रगति वादा जोड़ता है और अब यह अन्य वादों की तरह ही उपयोग करना आसान है:

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

इसे जीथूब पर देखें


आपको IFI फ़ैक्टरी का उपयोग करने का तरीका पसंद आया। मैं उस तकनीक को नहीं जानता था!
कोडआर्टिस्ट

यह वर्तमान में यहाँ सुझाया गया सबसे अच्छा समाधान है।
एटोमलेस नोव

2
कार्य करना और सुरुचिपूर्ण समाधान लेकिन आप इस बात से अवगत हो सकते हैं कि यह आपके मौजूदा कोड को तोड़ सकता है क्योंकि यह सभी कॉलों को ब्रेकडाउन और असफलता के लिए तोड़ता है। यह सभी गैर मानक विशेषताओं को भी स्ट्रिप्स करता है जो आप एक jqXHR ऑब्जेक्ट पर सेट करते हैं। यह अपलोडप्रोग्रेड कॉलबैक के लिए "यह" भी संदर्भ प्रदान नहीं करता है (शायद प्रगति के लिए समान है लेकिन परीक्षण नहीं किया गया है) क्योंकि यह jqXHR के लिए सभी मानक वादों के लिए किया जाता है। इसलिए आपको संदर्भ बंद करने की आवश्यकता होगी।
फ्रैंक

4
मुझे त्रुटि मिलती है: TypeError: $.ajax(...).progress(...).progressUpload is not a function.... क्या समस्या है?
यूनिवर्सल ग्रास

@UniversalGrasp हाय, कृपया, github पर एक समस्या खोलें और आपने क्या किया है, इसके बारे में जानकारी प्रदान करें। इस लाइब्रेरी को उम्र के लिए अपडेट नहीं किया गया था :) हो सकता है कि कुछ jQuery में ही बदल गया हो
likerRr

5

मैंने अजाक्स वस्तु के निर्माण में अवरोधन के तीन अलग-अलग तरीकों की कोशिश की:

  1. मेरा पहला प्रयास था xhrFields, लेकिन वह केवल एक श्रोता के लिए अनुमति देता है, केवल डाउनलोड (अपलोड नहीं) प्रगति के लिए संलग्न करता है, और अनावश्यक प्रतिलिपि-और-पेस्ट की तरह लगता है की आवश्यकता है।
  2. मेरे दूसरे प्रयास progressने लौटे वादे के लिए एक फ़ंक्शन संलग्न किया , लेकिन मुझे अपने स्वयं के हैंडलर्स को बनाए रखना था। मुझे हैंडलर संलग्न करने के लिए एक अच्छी वस्तु नहीं मिली क्योंकि एक जगह मैं एक्सएचआर तक पहुंच सकता हूं और दूसरा मैं jQuery के एक्सएचआर तक पहुंच सकता हूं, लेकिन मुझे कभी भी स्थगित ऑब्जेक्ट (केवल इसका वादा) तक पहुंच नहीं थी।
  3. मेरे तीसरे प्रयास ने मुझे हैंडलर संलग्न करने के लिए एक्सएचआर के लिए सीधी पहुंच दी, लेकिन फिर से बहुत कॉपी-और-पेस्ट कोड की आवश्यकता थी।
  4. मैंने अपने तीसरे प्रयास को लपेट लिया और ajaxअपने साथ jQuery का स्थान ले लिया । एकमात्र संभावित कमी यह है कि अब आप अपनी 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 );

इसलिए मैंने सिर्फ आपके समाधान को लागू करने की कोशिश की, लेकिन यह कोड मेरे लिए समझने के लिए थोड़ा बहुत समर्थक है - मैं इसका उपयोग कैसे करूं? मैंने अपने पूरे कोड को अपने डॉक्यूमेंट के पहले ही पेस्ट कर दिया था। पहले से ही कोशिश कर रहा था $.ajax({ ... }).progress(function(evl) { console.log(evl); });लेकिन कुछ नहीं हो रहा है। क्या आप मेरी मदद कर सकते हैं? :)
पैट्रिक डावाडर

आप किस संस्करण का उपयोग कर रहे हैं?
फ़्लो शिल्ड

@FloSchild, कृपया अपने कोड को केवल अपनी स्वयं की फ़ॉर्मेटिंग वरीयताओं के लिए संपादित न करें।
18 मई को MarkMYoung

3

jQuery का एक AjaxSetup()फ़ंक्शन है जो आपको वैश्विक अजाक्स संचालकों को पंजीकृत करने की अनुमति देता है जैसे कि beforeSendऔर completeसभी अजाक्स कॉल के साथ-साथ आप जिस xhrवस्तु की तलाश कर रहे हैं उसे करने के लिए ऑब्जेक्ट को एक्सेस करने की अनुमति देते हैं


2
लिंक के लिए धन्यवाद। क्या आप अपने उत्तर में एक उदाहरण शामिल कर सकते हैं?
माइकल शेपर

$ .ajaxSetup ({xhr: function () {कंसोल.लॉग ('सेटअप XHR ...';};}));
फ्लो शिल्ड

7
और एक उदाहरण जो प्रश्न का उत्तर देता है? मुझे डर है कि मैं ऐसा जवाब नहीं दे सकता, जो मुझे बहुत फिजूलखर्ची और पढ़ने को छोड़ दे, खासकर तब जब जुड़ा हुआ पेज प्रगति के बारे में कुछ न कहे। ईमानदारी से, मैं इस बारे में उलझन में, विशेष रूप से उस पृष्ठ पर चेतावनी दी है, का कहना है कि 'नोट: ग्लोबल कॉलबैक कार्यों उनके संबंधित वैश्विक अजाक्स ईवेंट हैंडलर तरीकों के साथ स्थापित किया जाना चाहिए .ajaxStart(), .ajaxStop(), .ajaxComplete(), .ajaxError(), .ajaxSuccess(), .ajaxSend()विकल्प के भीतर से -rather के लिए आपत्ति $.ajaxSetup()। ' < api.jquery.com/jQuery.ajaxSetup/#entry-longdesc >
माइकल शीश

1
डॉक्स से : भविष्य के अजाक्स अनुरोधों के लिए डिफ़ॉल्ट मान सेट करें। इसके उपयोग की अनुशंसा नहीं की जाती है।
ओविंद

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

यह चल रहे PHP स्क्रिप्ट की प्रगति दिखाता है, AJAX कॉल की नहीं।
साइनस मैकेवेटी

-3

अजाक्स अनुरोध की प्रगति प्रदर्शित करने के लिए चरणों का पालन करें:

  1. Html & CSS का उपयोग करके एक स्पिनर बनाएं या बूटस्ट्रैप स्पिनर का उपयोग करें।
  2. स्पिनर को तब प्रदर्शित करें जब एंड-यूज़र अनंत लूप के लिए या थ्रेसहोल्ड लिमिट टाइम के लिए AJAX डेटा के लिए अनुरोध कर रहा हो।
  3. तो, AJAX अनुरोध के SUCCESS / ERROR परिणाम के बाद, वर्तमान में प्रदर्शित होने वाले स्पिनर को हटा दें और अपने परिणाम दिखाएं।

इसे आसान बनाने के लिए मैं आपको इस उद्देश्य के लिए स्पिनर को गतिशील रूप से प्रदर्शित करने और छिपाने के लिए JS क्लासेस का उपयोग करने की सलाह देता हूं।

आशा है कि ये आपकी मदद करेगा!


2
यह "प्रगति नहीं" हो रहा है, केवल एक "प्रतीक्षा" एनीमेशन दिखा रहा है।
सिनुस मैकॉवेती
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.