programing

jAJAX 스트림을 증분적으로 읽으시겠습니까?

fastcode 2023. 3. 1. 13:47
반응형

jAJAX 스트림을 증분적으로 읽으시겠습니까?

나는 이 질문을 읽었지만 내 질문에 정확히 답하지 않는다.아쉽게도 마지막으로 AJAX를 본 이후 XHR 오브젝트에 변화가 생긴 것 같습니다.따라서 더 이상 직접 접속할 수 없습니다.responseText입력이 완료되기 전에 종료합니다.

제어할 수 없는 서버에서 HTTP를 통해 CSV 데이터를 가져오기 위해 AJAX(가능하다면 jQuery, 그러나 제안에는 열려 있음)를 사용하는 페이지를 작성해야 합니다.응답 데이터는 매우 클 수 있으며, 1메가바이트의 텍스트는 드물지 않습니다.

서버는 스트림 친화적입니다.JavaScript에서 직접 반환되는 데이터 스트림에 액세스할 수 있는 방법은 아직 있습니까?

중간에 있는 PHP 코드를 쓸 수 있는 옵션도 있습니다만, 가능하면 피하고 싶습니다.

관련된 경우 사용자가 최신 버전의 Firefox/Chrome/Opera를 사용하고 있으며 이전 브라우저와의 호환성은 문제가 되지 않는다고 가정합니다.

텍스트 또는 HTML을 출력할 때 이것은 매우 간단합니다.다음은 예를 제시하겠습니다.

(단, 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...');

HTML 파일

<!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 개체가 차례로 있는 경우 파이프로 내려오는 동안 한 번에 하나씩 로드할 수 있습니다.

그래서 위에서 코드를 수정했는데...

  1. FILE 에서 PHP echo $val;로로 합니다.echo '{"name":"'.$val.'"};'JSON을 사용하다

  2. 행 를 「HTML FILE」24 에서 변경.console.log(this_response); 접속합니다.

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

    이 기본 코드는 브라우저에 도달하는 각 "chunk"가 유효한 JSON 개체라고 가정합니다.패킷이 어떻게 착신할지를 예측할 수 없기 때문에, 반드시 이러한 것은 아닙니다.반콜론에 근거해 문자열을 분할할 필요가 있습니다(또는 다른 구분 문자를 사용할 필요가 있습니다).

마세요application/json

헤더를 다음으로 변경하지 마십시오.application/json - 을 3일 동안 했어요.이 「」인 .application/json브라우저는 완전 완료와 마찬가지로 응답이 완료될 때까지 기다립니다. 후 JSON인지 됩니다., 은 「」입니다.{...};{...};{...};JSON하다jqXHR.done메서드는 완전한 응답을 JSON으로 해석할 수 없기 때문에 오류가 있다고 가정합니다.

코멘트에 기재되어 있듯이, 클라이언트측에서 다음의 방법으로 이 체크를 무효로 할 수 있습니다.

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

어떤 사람들은 이것이 유용하다고 생각하길 바란다.

XMLHttpRequest.js 사용

https://github.com/ilinsky/xmlhttprequest

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

  • XMLHttpRequest 1.0 객체의 방해받지 않는 표준 준거(W3C) 크로스 브라우저 구현 제공
  • 네이티브 XMLHttpRequest 오브젝트 구현에서 발견된 모든 브라우저의 기호가 수정됩니다.
  • XMLHttpRequest 객체액티비티의 투과적인 로깅을 이노블로 합니다.

PHP에서 긴 폴링을 사용하려면:

output.displacesput.displaces:

<?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.syslog:

<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

당신은 이것을 위해 javascript를 바로 사용하기를 원할 것입니다.그 이유는 콜백이 실행되기를 기다리지 않고 지속적으로 폴링을 하기 때문입니다.여기에는 jQuery가 필요하지 않습니다. 매우 간단합니다.Ajax Patterns 웹사이트에는 이에 대한 좋은 소스 코드가 있습니다.

기본적으로 응답의 마지막 위치를 추적하고 해당 위치를 지나 더 많은 텍스트를 주기적으로 폴링하면 됩니다.다른 점은 이벤트 전체를 구독하고 폴링을 중지할 수 있다는 것입니다.

서버가 스트림 친화적(비동기적)이며 jquery 솔루션을 찾고 있다고 하셨기 때문에 jQuery Stream Plugin을 확인해 보셨습니까?

그것은 정말 사용하기 쉽고 많은 것에 대해 걱정할 필요가 없습니다.서류되어 있어요.

최대 허용 크기 제한에 계속 도달하는 큰 JSON 페이로드로 그리드를 공급해야 했습니다.MVC와 jquery를 사용하고 있었기 때문에 위의 AlexMorley-Finch의 솔루션을 채택했습니다.

서버 코드는 "Web API를 사용하여 데이터 스트리밍"에서 가져온 것입니다.https://github.com/DblV/StreamingWebApi도 참조해 주세요.

public class StreamingController : ApiController
{

    [HttpGet]
    [ActionName("GetGridDataStream")]
    public HttpResponseMessage GetGridDataStream(string id)
    {
        var response = Request.CreateResponse();
        DynamicData newData = new DynamicData();
        var res = newData.GetDataRows(id);
        response.Content = new PushStreamContent((stream, content, context) =>
        { 
            foreach (var record in res)
            {
                var serializer = new JsonSerializer();
                using (var writer = new StreamWriter(stream))
                {
                    serializer.Serialize(writer, record);
                    stream.Flush();
                }

               // Thread.Sleep(100);
            }

            stream.Close();
        });

        return response;
    }
}

이렇게 하면 쉼표로 구분하고 [ ]을(를) json으로 구문 분석해야 하는 {json object}{json object}{json object}의 스트림이 생성되었습니다.

클라이언트 코드가 다음과 같이 누락된 문자를 제공받았습니다.

 var jsonData = {}; 

 $.ajax("api/Streaming/GetGridDataStream/" + viewName, {
    xhrFields: {
            onprogress: function (e) { 
                // console.log(this_response);
            }
        }
    }, { dataType: "text" }) //<== this is important for JSON data
    .done(function (data) { 

        data = "[" + data.replace(/\}\{/gi, "},{") + "]";

        jsonData["DataList"] = JSON.parse(data);
        //more code follows to create grid
    })
    .fail(function (data) {
        console.log('Error: ', data);
    });

다른 사용자가 사용하는 데 도움이 되었으면 합니다.넷 MVC 및 jQuery.

JQuery를 사용하여 이를 실현하는 간단한 방법은 다음과 같습니다(OP의 요청에 따름).

먼저 https://gist.github.com/chrishow/3023092에서 다음 코드를 실행하여 onready state change를 지원하도록 agax 객체를 확장합니다(이 응답의 하단에 기재되어 있습니다).그런 다음 xhr.responseText에서 새로운 텍스트를 확인하는 onreadystatechange 함수를 사용하여 ajax에 호출합니다.

보다 고급스러운 정보를 얻고 싶다면 여기에 설명된 것처럼 읽을 때마다 responseText 데이터를 지울 수 있습니다.

예를 들어, https://jsfiddle.net/g1jmwcmw/1/, 에서 응답을 다운로드하여 다음 코드를 사용하여 콘솔창 내에서 청크로 출력합니다(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>

언급URL : https://stackoverflow.com/questions/7740646/jquery-read-ajax-stream-incrementally

반응형