我正在使用JSON流,并尝试使用fetch来使用它。流每隔几秒发出一些数据。使用fetch来使用流只允许我在流关闭服务器端时访问数据。例如:
var target; // the url.
var options = {
method: "POST",
body: bodyString,
}
var drain = function(response) {
// hit only when the stream is killed server side.
// response.body is always undefined. Can't use the reader it provides.
return response.text(); // or response.json();
};
var listenStream = fetch(target, options).then(drain).then(console.log).catch(console.log);
/*
returns a data to the console log with a 200 code only when the server stream has been killed.
*/
但是,已经有几个数据块已经发送到客户端。
在浏览器中使用节点启发式方法就像每次发送事件一样:
var request = require('request');
var JSONStream = require('JSONStream');
var es = require('event-stream');
request(options)
.pipe(JSONStream.parse('*'))
.pipe(es.map(function(message) { // Pipe catches each fully formed message.
console.log(message)
}));
我错过了什么?我的直觉告诉我,fetch应该能够模仿pipe
或流功能。
答案 0 :(得分:15)
response.body
可让您以流的形式访问响应。阅读流:
fetch(url).then(response => {
const reader = response.body.getReader();
reader.read().then(function process(result) {
if (result.done) return;
console.log(`Received a ${result.value.length} byte chunk of data`);
return reader.read().then(process);
}).then(() => {
console.log('All done!');
});
});
Here's a working example of the above
获取流比XHR更具内存效率,因为完整响应不会在内存中缓冲,而result.value
是Uint8Array
,这对二进制数据更有用。如果您需要文字,可以使用TextDecoder
:
fetch(url).then(response => {
const reader = response.body.getReader();
const decoder = new TextDecoder();
reader.read().then(function process(result) {
if (result.done) return;
const text = decoder.decode(result.value, {stream: true});
console.log(text);
return reader.read().then(process);
}).then(() => {
console.log('All done!');
});
});
Here's a working example of the above
很快TextDecoder
将成为变换流,允许您执行response.body.pipeThrough(new TextDecoder())
,这更简单,并允许浏览器进行优化。
至于你的JSON案例,流式JSON解析器可能有点大而复杂。如果您控制数据源,请考虑由换行符分隔的JSON块的格式。这很容易解析,并且在大多数工作中都依赖于浏览器的JSON解析器。 Here's a working demo,可以在较慢的连接速度下看到好处。
我还written an intro to web streams,其中包括他们在服务工作者中的使用。您可能还对使用JavaScript模板文字来创建streaming templates的有趣黑客感兴趣。
答案 1 :(得分:0)
原来我可以让XHR工作 - 这并没有真正回应请求与获取问题。经过几次尝试和正确的操作顺序才能做到正确。这是抽象的代码。 @jaromanda是对的。
var _tryXhr = function(target, data) {
console.log(target, data);
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function () {
console.log("state change.. state: "+ this.readyState);
console.log(this.responseText);
if (this.readyState === 4) {
// gets hit on completion.
}
if (this.readyState === 3) {
// gets hit on new event
}
};
xhr.open("POST", target);
xhr.setRequestHeader("cache-control", "no-cache");
xhr.setRequestHeader("Content-Type", "application/json");
xhr.send(data);
};