javascript - 如何通过 PostMessage 将 Serviceworker 响应主体 ReadableByteStream 作为 Blob 返回?

标签 javascript google-chrome blob postmessage service-worker

我正在使用 ServiceWorker在 Chrome 中,我使用 postMessage 在网页和 serviceworker 之间进行通信。通信包括请求和接收文件数据(存储为 Blob)。

假设我正在存储一个这样的 Blob:

// param.name = "http://foo.css",
// param.content = new Blob(
//   ["span%2C%20div%20%7Bborder%3A%201px%20solid%20red%20!important%3B%7D"],
//   {type: "text/css"}
// )

caches.open(CURRENT_CACHE)
    .then(function(cache) {
      request = new Request(param.name, {mode: 'no-cors'}),
      response = new Response(param.content);
      cache.put(request, response)
        .then(function() {
          event.ports[0].postMessage({
            error: null
          });
        });

这会正确存储文件,我可以使用 fetch() 正确检索它,而不是从网络请求它。但是如果我像这样使用 ma​​tch() 方法:

caches.open(CURRENT_CACHE)
  .then(function(cache) {
    return cache.match(param.name)
      .then(function(response) {
        return response.clone().blob();
      })
      .then(function (converted_response) {
        if (converted_response) {
          event.ports[0].postMessage({
            error: null,
            data: converted_response
          });
        } else {
          event.ports[0].postMessage({
            error: {
              'status': 404,
              'message': 'Item not found in cache.'
            }
          });
        }
      });

我在 response.body 中收到了一个 ReadableByteStream 并且不知道如何提取内容并通过 postMessage 传回它。

我目前正在尝试根据 this articleclone() 响应,因为仅通过 postMessage 返回完整响应将失败,抛出 DataCloneError: Failed to execute postMessage on MessagePort,我也没有找到很多相关信息。

如果我克隆,我可以调用 blob 给我一个新的(?)Blob,然后我可以传回它,但它只会在尝试读取时返回 undefined:

var r = new FileReader()
return r.readAsText(my_blob);

如果你想自己试试:

要将文件存储在 ServiceWorker 中,请在其检查器控制台中运行:

caches.keys()
  .then(function (list) {return caches.open(list[0])})
  .then(function (cache) 
      request = new Request("http://foo.css", {mode: 'no-cors'}),
      response = new Response(new Blob(
        ["span%2C%20div%20%7Bborder%3A%201px%20solid%20red%20!important%3B%7D"],
        {type: "text/css"}
      ));
      cache.put(request, response)
        .then(function() {
          event.ports[0].postMessage({
            error: null
          });
        });
    })
    .catch(function(error) {
      event.ports[0].postMessage({
        error: {'message': error.toString()}
      });
    });

检索:

caches.keys()
  .then(function (list) {return caches.open(list[0])})
  .then(function (cache) {return cache.match("http://foo.css")})
  .then(function(answer) {
     console.log(answer.body);
     var b = response.body;
     return answer.clone().blob();
   })
  .then(function (x) {
      console.log(x);
      var r = new FileReader();
      return r.readAsText(x)
  })
  .then(function (y) {
    console.log("DONE");
    // undefined
    console.log(y);
  })

问题: 关于如何处理 ReadableByteStream 并将其内容/mime 类型提取为 Blob 以便我可以通过 postMessage 传回的任何提示?谢谢!

最佳答案

If I clone, I can call blob giving me a new(?) Blob, which I can then pass back but which only return undefined when trying to read:

var r = new FileReader()
return r.readAsText(my_blob);

那是因为你没有使用 readAsText(my_blob)适本地。您必须在文件读取器的 onload 属性中附加一个回调,并在回调被调用时解析一个 promise。我的意思是,而不是:

.then(function (x) {
  console.log(x);
  var r = new FileReader();
  return r.readAsText(x)
})

使用:

.then(function (x) {
  return new Promise(function (resolve) {
    var r = new FileReader();
    r.onload = resolve;
    r.readAsText(x);
  });
})

Question: Any tips how to handle ReadableByteStream and extract it's content/mime-type as Blob so I can pass it back over postMessage? Thanks!

要提取其 mime 类型,您可以简单地读取属性 type来自 blob 对象。

.then(function (x) {
  console.log(x.type); // <-- the mime type
  return new Promise(function (resolve) {
    var r = new FileReader();
    r.onload = resolve;
    r.readAsText(x);
  });
})

关于javascript - 如何通过 PostMessage 将 Serviceworker 响应主体 ReadableByteStream 作为 Blob 返回?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36617814/

相关文章:

javascript - 为用户右键单击和检查 Firefox 或 Chrome 中的元素创建事件处理程序

java - 将 BLOB 图像转换为位图并显示在 ImageView 中

javascript - 带有错误符号的 CSS 内容

javascript - 我应该导入什么来使用 jquery 数据表?

Javascript - 在所选元素上仅获取两位小数

javascript - 将变量的内容附加到 html 内的文本文件

google-chrome - Chrome在docker网络内部无法访问

google-chrome - chrome处于 headless 模式: Provide credentials/auth for proxy

javascript - 从 Node.js 读取 Oracle 中的 BLOB

python - 使用 Python 在 MySQL 中保存 BLOBS