使用 Asynchronous ReadableStream with Response 从 Service Worker 的 fetch 事件返回 HTML [英] Use Asynchronous ReadableStream with Response to return HTML from fetch event of Service Worker

查看:28
本文介绍了使用 Asynchronous ReadableStream with Response 从 Service Worker 的 fetch 事件返回 HTML的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题类似于我的另一个问题,但考虑到 ReadableStream 内部的异步性质.

This question is similar to my other question but takes into account asynchronous nature inside the ReadableStream.

这是我现在的测试代码:

This is my test code now:

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 项.

The above code is not rendered by the browser and I'm not sure why. According to examples online it seems like it should work. But it doesn't appear to be reading any of the enqueue items.

请注意,在我的另一个问题中,答案至少呈现了第一个响应:

Note in my other question the answer at least rendered the first response:

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

这似乎是有道理的,因为它一次读取所有内容而不考虑流是否完成.

Which seems to make sense as it is reading everything at once without regard to if the stream is finished.

我使用过的资源:

https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream#Examples

https://philipwalton.com/articles/smaller-html-payloads-with-service-workers/

推荐答案

当你将 Uint8Array 放入 controller.enqueue 时,看起来像 stream> 方法.

Looks like stream likes when you are putting Uint8Array in controller.enqueue method.

借助 TextEncoder 你的例子有效.

With the help of TextEncoder your example works.

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

这篇关于使用 Asynchronous ReadableStream with Response 从 Service Worker 的 fetch 事件返回 HTML的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆