这个问题与我的其他问题类似,但考虑到了
ReadableStream
内部的异步性质。
这是我现在的测试代码:
const stream = new ReadableStream({
start(c) {
let i = 1
const t = setInterval(test, 5e2)
function test() {
c.enqueue("<h1>Yellow!</h1>")
if (i++ === 5) {
clearInterval(t)
c.close()
}
}
}
})
event.respondWith(new Response(stream, {headers: {"content-type": "text/html"}}))
上面的代码不是由浏览器渲染的,我不知道为什么。 根据在线示例,它似乎应该有效。但它似乎没有读取任何
enqueue
项目。
请注意,在我的其他问题中,答案至少给出了第一个响应:
const createStream = () => new ReadableStream({
start(controller) {
controller.enqueue("<h1 style=\"background: yellow;\">Yellow!</h1>")
controller.close()
}
})
const secondStream = createStream().getReader();
secondStream.read()
.then(({
value
}) => {
return new Response(value, {
headers: {
"Content-Type": "text/html"
}
});
})
.then(response => response.text())
.then(text => {
console.log(text);
});
这似乎是有道理的,因为它会立即读取所有内容,而不考虑流是否完成。
我使用过的资源:
https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream#Examples
https://philipwalton.com/articles/smaller-html-payloads-with-service-workers/
看起来
stream
喜欢将 Uint8Array
放入 controller.enqueue
方法中。
TextEncoder
的帮助下,你的示例可以工作。
const data = [
{name: "Yellow", value: 'yellow'},
{name: "Green", value: 'green'},
{name: "Blue", value: 'blue'},
{name: "Red", value: 'red'},
{name: "Orange", value: 'orange'},
]
const encoder = new TextEncoder();
const stream = new ReadableStream({
start(controller) {
let i = 1
const handle = setInterval(test, 5e2)
function test() {
const {name, value} = data[i - 1];
controller.enqueue(encoder.encode(`<h1 style="color: ${value};">${name}!</h1>`))
if (i++ === 5) {
clearInterval(handle)
controller.close()
}
}
}
})
new Response(stream, {headers: {"content-type": "text/html"}})
.text().then(text => {
document.body.innerHTML = text;
})
使用更现代语法的类似示例(请注意,ReadableStream.from到目前为止仅在 Firefox、Node 和 Deno 中实现)。技巧仍然与 Jozef 的答案相同:使用
TextEncoder
。
const encoder = new TextEncoder()
const generator = async function* () {
yield encoder.encode('a')
yield encoder.encode('b')
yield encoder.encode('c')
}
const res = new Response( ReadableStream.from(generator()) )
console.log(await res.text())