jQuery AJAX स्ट्रीम incrementally पढ़ा?




javascript-events long-polling (4)

JQuery का उपयोग करके इसे प्राप्त करने का एक सीधा तरीका यहां है (जैसा ओपी द्वारा अनुरोध किया गया है):

सबसे पहले, https://gist.github.com/chrishow/3023092 (इस प्रतिक्रिया के निचले हिस्से में संलग्न) से नीचे दिए गए कोड को चलाकर ऑनएस्टस्टेटchange का समर्थन करने के लिए AJAX ऑब्जेक्ट का विस्तार करें। फिर केवल एक ऑनएक्सस्टेटेन्चेंज फ़ंक्शन का उपयोग करके AJAX को कॉल करें जो नए टेक्स्ट के लिए xhr.responseText की जांच करेगा।

यदि आप फैनसीयर भी प्राप्त करना चाहते हैं, तो आप प्रत्येक बार जब इसे पढ़ते हैं, तो प्रतिक्रिया डेटा को साफ़ कर सकते हैं, जैसे कि here वर्णित)।

उदाहरण के लिए, https://jsfiddle.net/g1jmwcmw/1/ , जो https://code.jquery.com/jquery-1.5.js से प्रतिक्रिया डाउनलोड करेगा और इसे आपके कंसोल विंडो के अंदर हिस्सों में आउटपुट करेगा, इसका उपयोग करके नीचे कोड (जिसे आप सिर्फ एक HTML पृष्ठ में कॉपी कर सकते हैं और फिर अपने ब्राउज़र में खोल सकते हैं):

<!-- jquery >= 1.5. maybe earlier too but not sure -->
<script src=https://code.jquery.com/jquery-1.5.min.js></script>
<script>
/* One-time setup (run once before other code)
 *   adds onreadystatechange to $.ajax options
 *   from https://gist.github.com/chrishow/3023092)
 *   success etc will still fire if provided
 */
$.ajaxPrefilter(function( options, originalOptions, jqXHR ) {
    if ( options.onreadystatechange ) {
        var xhrFactory = options.xhr;
        options.xhr = function() {
            var xhr = xhrFactory.apply( this, arguments );
            function handler() {
                options.onreadystatechange( xhr, jqXHR );
            }
            if ( xhr.addEventListener ) {
                xhr.addEventListener( "readystatechange", handler, false );
            } else {
                setTimeout( function() {
                    var internal = xhr.onreadystatechange;
                    if ( internal ) {
                        xhr.onreadystatechange = function() {
                            handler();
                            internal.apply( this, arguments ); 
                        };
                    }
                }, 0 );
            }
            return xhr;
        };
    }
});

// ----- myReadyStateChange(): this will do my incremental processing -----
var last_start = 0; // using global var for over-simplified example
function myReadyStateChange(xhr /*, jqxhr */) {
    if(xhr.readyState >= 3 && xhr.responseText.length > last_start) {
        var chunk = xhr.responseText.slice(last_start);
        alert('Got chunk: ' + chunk);
        console.log('Got chunk: ', chunk);
        last_start += chunk.length;
    }
}

// ----- call my url and process response incrementally -----
last_start = 0;
$.ajax({
  url: "https://code.jquery.com/jquery-1.5.js", // whatever your target url is goes here
  onreadystatechange: myReadyStateChange
});

</script>

मैंने इस सवाल को पढ़ा है लेकिन यह मेरे प्रश्न का बिल्कुल जवाब नहीं देता है। दुर्भाग्यवश, ऐसा लगता है कि एक्सएचआर ऑब्जेक्ट में चीजें बदल गई हैं क्योंकि मैंने आखिरकार AJAX को देखा था, इसलिए पॉप्युलेट होने से पहले responseText को सीधे एक्सेस करना संभव नहीं है।

मुझे एक ऐसा पृष्ठ लिखना है जो AJAX का उपयोग करता है (अधिमानतः jQuery, लेकिन मैं सुझावों के लिए खुला हूं) सर्वर से HTTP के माध्यम से सीएसवी डेटा पुनर्प्राप्त करने के लिए मेरा कोई नियंत्रण नहीं है। प्रतिक्रिया डेटा काफी बड़ा हो सकता है; पाठ का एक मेगाबाइट असामान्य नहीं है।

सर्वर स्ट्रीम-फ्रेंडली है। डेटा की स्ट्रीम तक पहुंच प्राप्त करने के लिए अभी भी कोई तरीका है क्योंकि इसे वापस किया जा रहा है, सीधे जावास्क्रिप्ट से?

मेरे पास कुछ PHP कोड लिखने का विकल्प है जो मध्य में रहता है और कुछ प्रकार के "धूमकेतु" तकनीक (लंबे मतदान, इवेंटसोर्स इत्यादि) का उपयोग करता है, लेकिन यदि संभव हो तो मैं इससे बचना पसंद करूंगा।

यदि यह प्रासंगिक है, तो इस प्रश्न के लिए मान लें कि उपयोगकर्ताओं के पास फ़ायरफ़ॉक्स / क्रोम / ओपेरा का नवीनतम संस्करण है और पुरानी ब्राउज़र संगतता कोई समस्या नहीं है।


XMLHttpRequest.js का उपयोग करें

https://github.com/ilinsky/xmlhttprequest

http://code.google.com/p/xmlhttprequest

  • XMLHttpRequest 1.0 ऑब्जेक्ट के अविभाज्य मानक-अनुपालन (डब्ल्यू 3 सी) क्रॉस-ब्राउज़र कार्यान्वयन प्रदान करता है
  • अपने मूल XMLHttpRequest ऑब्जेक्ट कार्यान्वयन में देखे गए सभी ब्राउज़रों क्विर्क को ठीक करता है
  • XMLHttpRequest ऑब्जेक्ट गतिविधि के पारदर्शी लॉगिंग को सक्षम करता है

PHP के साथ लंबे मतदान का उपयोग करने के लिए:

output.php:

<?php
header('Content-type: application/octet-stream');

// Turn off output buffering
ini_set('output_buffering', 'off');
// Turn off PHP output compression
ini_set('zlib.output_compression', false);
// Implicitly flush the buffer(s)
ini_set('implicit_flush', true);
ob_implicit_flush(true);
// Clear, and turn off output buffering
while (ob_get_level() > 0) {
    // Get the curent level
    $level = ob_get_level();
    // End the buffering
    ob_end_clean();
    // If the current level has not changed, abort
    if (ob_get_level() == $level) break;
}
// Disable apache output buffering/compression
if (function_exists('apache_setenv')) {
    apache_setenv('no-gzip', '1');
    apache_setenv('dont-vary', '1');
}

// Count to 20, outputting each second
for ($i = 0;$i < 20; $i++) {
    echo $i.str_repeat(' ', 2048).PHP_EOL;
    flush();
    sleep(1);
}

run.php:

<script src="http://code.jquery.com/jquery-1.6.4.js"></script>
<script src="https://raw.github.com/ilinsky/xmlhttprequest/master/XMLHttpRequest.js"></script>

<script>
$(function() {
    var xhr = new XMLHttpRequest();
    xhr.open('GET', '/longpoll/', true);
    xhr.send(null);
    var timer;
    timer = window.setInterval(function() {
        if (xhr.readyState == XMLHttpRequest.DONE) {
            window.clearTimeout(timer);
            $('body').append('done <br />');
        }
        $('body').append('state: ' + xhr.readyState + '<br />');
        console.log(xhr.responseText);
        $('body').append('data: ' + xhr.responseText + '<br />');
    }, 1000);
});
</script>

यह आउटपुट होना चाहिए:

state: 3
data: 0
state: 3
data: 0 1
state: 3
data: 0 1 2
state: 3
data: 0 1 2 3
state: 3
data: 0 1 2 3 4
...
...
...
state: 3
data: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
state: 3
data: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
state: 3
data: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
done
state: 4
data: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 

IE के लिए आपको XDomainRequest में देखना होगा

http://blogs.msdn.com/b/ieinternals/archive/2010/04/06/comet-streaming-in-internet-explorer-with-xmlhttprequest-and-xdomainrequest.aspx

http://msdn.microsoft.com/en-us/library/cc288060(VS.85).aspx


चूंकि आप कहते हैं कि आपका सर्वर स्ट्रीम अनुकूल है (एसिंक्रोनस) और एक jquery समाधान की तलाश में था, क्या आपने jQuery स्ट्रीम प्लगइन की जांच की है ?

यह उपयोग करना वास्तव में आसान है और आपको वास्तव में कुछ भी ज्यादा चिंता करने की अनुमति नहीं देता है। इसमें बहुत अच्छा documentation भी है।


टेक्स्ट या एचटीएमएल आउटपुट करते समय यह काफी सरल है। नीचे एक उदाहरण है।

(यदि आप JSON आउटपुट करने का प्रयास करते हैं तो आप समस्याओं में भाग लेंगे, हालांकि मैं आगे से निपटूंगा।)

PHP फ़ाइल

header('Content-type: text/html; charset=utf-8');
function output($val)
{
    echo $val;
    flush();
    ob_flush();
    usleep(500000);
}
output('Begin... (counting to 10)');
for( $i = 0 ; $i < 10 ; $i++ )
{
    output($i+1);
}
output('End...');

एचटीएमएल फ़ाइल

<!DOCTYPE>
<html>
    <head>
        <title>Flushed ajax test</title>
        <meta charset="UTF-8" />
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
    </head>
    <body>
        <script type="text/javascript">
        var last_response_len = false;
        $.ajax('./flushed-ajax.php', {
            xhrFields: {
                onprogress: function(e)
                {
                    var this_response, response = e.currentTarget.response;
                    if(last_response_len === false)
                    {
                        this_response = response;
                        last_response_len = response.length;
                    }
                    else
                    {
                        this_response = response.substring(last_response_len);
                        last_response_len = response.length;
                    }
                    console.log(this_response);
                }
            }
        })
        .done(function(data)
        {
            console.log('Complete response = ' + data);
        })
        .fail(function(data)
        {
            console.log('Error: ', data);
        });
        console.log('Request Sent');
        </script>
    </body>
</html>

अगर मुझे JSON के साथ ऐसा करने की ज़रूरत है तो क्या होगा?

वास्तव में एक एकल JSON ऑब्जेक्ट को लोड करना संभव नहीं है (इसे पूरी तरह लोड होने से पहले) क्योंकि जब तक आपके पास पूर्ण ऑब्जेक्ट नहीं है, तो वाक्यविन्यास हमेशा अमान्य होगा।

लेकिन अगर आपकी प्रतिक्रिया में कई JSON ऑब्जेक्ट्स हैं, तो एक दूसरे के बाद, तो एक बार में लोड करना संभव है, क्योंकि वे पाइप नीचे आते हैं।

तो मैंने ऊपर अपना कोड tweaked ...

  1. echo $val; से PHP फ़ाइल लाइन 4 बदलना echo $val; echo '{"name":"'.$val.'"};' । यह JSON ऑब्जेक्ट्स की एक श्रृंखला आउटपुट करता है।

  2. console.log(this_response); से एचटीएमएल फ़ाइल लाइन 24 बदलना console.log(this_response); सेवा मेरे

    this_response = JSON.parse(this_response);
    console.log(this_response.name);
    

    ध्यान दें कि यह प्राथमिक कोड मानता है कि ब्राउज़र में आने वाले प्रत्येक "खंड" वैध JSON ऑब्जेक्ट है। यह हमेशा ऐसा नहीं होगा क्योंकि आप भविष्यवाणी नहीं कर सकते कि पैकेट कैसे पहुंचेंगे - आपको अर्ध-कॉलन (या किसी अन्य विभाजक चरित्र के साथ आना) के आधार पर स्ट्रिंग को विभाजित करने की आवश्यकता हो सकती है।

application/json प्रयोग न करें

अपने हेडर को application/json बदलने के लिए मत - मैंने यह किया और यह मुझे 3 दिनों के लिए गुगलिंग कर रहा था। जब प्रतिक्रिया प्रकार application/json , तो ब्राउज़र पूरी तरह से पूरा होने तक प्रतिक्रिया पूरी होने तक प्रतीक्षा करता है। फिर पूर्ण प्रतिक्रिया को जांचने के लिए पार्स किया जाता है कि यह वास्तव में JSON है या नहीं। हालांकि हमारी पूर्ण प्रतिक्रिया {...};{...};{...}; जो वैध JSON नहीं है। jqXHR.done विधि मानती है कि एक त्रुटि हुई थी, क्योंकि पूर्ण प्रतिक्रिया JSON के रूप में पार्स नहीं की जा सकती है।

जैसा कि टिप्पणियों में बताया गया है, आप क्लाइंट पक्ष पर इस चेक को अक्षम कर अक्षम कर सकते हैं:

$.ajax(..., {dataType: "text"})

आशा है कि कुछ लोगों को यह उपयोगी लगेगा।







http-streaming