如何在客户端编写javascript以及时接收和解析`chunked`响应?

Fre*_*ind 35 ajax chunked

我正在使用play框架来生成分块响应.代码是:

class Test extends Controller {
    public static void chunk() throws InterruptedException {
        for (int i = 0; i < 10; i++) {
            String data = repeat("" + i, 1000);
            response.writeChunk(data);
            Thread.sleep(1000);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我使用浏览器访问时http://localhost:9000/test/chunk,我可以看到显示的数据每秒都在增加.但是,当我编写一个javascript函数来接收和处理数据时,发现它将阻塞直到收到所有数据.

代码是:

$(function(){
    $.ajax(
        "/test/chunked", 
        {
            "success": function(data, textStatus, xhr) {
                alert(textStatus);
            }
        }
    );
});
Run Code Online (Sandbox Code Playgroud)

收到所有数据后,我可以看到10秒后弹出一个消息框.

如何获取流并及时处理数据?

phi*_*kov 64

jQuery不支持,但你可以用普通的XHR做到这一点:

var xhr = new XMLHttpRequest()
xhr.open("GET", "/test/chunked", true)
xhr.onprogress = function () {
  console.log("PROGRESS:", xhr.responseText)
}
xhr.send()
Run Code Online (Sandbox Code Playgroud)

这适用于所有现代浏览器,包括IE 10 W3C规范在这里.

这里的缺点是xhr.responseText包含累积的响应.你可以用它串,但更好的办法是使用responseTyp的属性和使用slice上ArrayBuffer.

  • @ Edmondo1984 [github.com/ebay/jsonpipe](https://github.com/eBay/jsonpipe) (5认同)
  • 为什么使用ArrayBuffer更好? (2认同)
  • @ Edmondo1984,我最终创建了这个包,它允许比jsonpipe更有效的传输:https://www.npmjs.com/package/chunked-request (2认同)

rin*_*.io 7

很快我们应该可以使用ReadableStreamAPI(此处为 MDN 文档)。下面的代码似乎适用于 Chrome 版本 62.0.3202.94:

fetch(url).then(function (response) {
    let reader = response.body.getReader();
    let decoder = new TextDecoder();
    return readData();
    function readData() {
        return reader.read().then(function ({value, done}) {
            let newData = decoder.decode(value, {stream: !done});
            console.log(newData);
            if (done) {
                console.log('Stream complete');
                return;
            }
            return readData();
        });
    }
});
Run Code Online (Sandbox Code Playgroud)