如何在客户端编写 JavaScript 来及时接收和解析“分块”响应?

发布于 2024-11-25 19:13:44 字数 742 浏览 4 评论 0原文

我正在使用播放框架来生成分块响应。代码是:

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

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

代码是:

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

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

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

I'm using play framework, to generate chunked response. The code is:

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

When I use browser to visit http://localhost:9000/test/chunk, I can see the data displayed increased every second. But, when I write a javascript function to receive and handle the data, found it will block until all data received.

The code is:

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

I can see a message box popped up after 10s, when all the data received.

How to get the stream and handle the data in time?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

阿楠 2024-12-02 19:13:45

很快我们就应该能够使用 ReadableStream API ( 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();
        });
    }
});

Soon we should be able to use ReadableStream API (MDN docs here). The code below seems to be working with Chrome Version 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();
        });
    }
});
忘羡 2024-12-02 19:13:45

当完整的数据传输完成并且连接以 200 响应代码关闭时,将触发 success 事件。我相信您应该能够实现本机 onreadystatechanged 事件并查看数据包的到来。

the success event would fire when the complete data transmission is done and the connection closed with a 200 response code. I believe you should be able to implement a native onreadystatechanged event and see the data packets as they come.

几味少女 2024-12-02 19:13:44

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

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

这适用于所有现代浏览器 ,包括 IE 10。W3C 规范此处

这里的缺点是 xhr.responseText 包含累积的响应。您可以在其上使用子字符串,但更好的主意是使用 responseType 属性并在 ArrayBuffer 上使用 slice

jQuery doesn't support that, but you can do that with plain XHR:

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

This works in all modern browsers, including IE 10. W3C specification here.

The downside here is that xhr.responseText contains an accumulated response. You can use substring on it, but a better idea is to use the responseType attribute and use slice on an ArrayBuffer.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文