如何通过 PostMessage return Serviceworker 响应主体 ReadableByteStream 作为 Blob?
How to return a Serviceworker response body ReadableByteStream as Blob via PostMessage?
我在 Chrome 中使用 ServiceWorker 并使用 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() 正确检索它,而不是从网络请求它。但是如果我像这样使用 match() 方法:
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 传回。
我目前正在尝试 clone() 根据 this article 的响应,因为仅 return 通过 postMessage 获取完整响应将失败,抛出 DataCloneError:无法在 MessagePort 上执行 postMessage,我也没有找到很多相关信息。
如果我克隆,我可以调用 blob 给我一个新的(?)Blob,然后我可以传回它,但在尝试读取时只有 return 未定义:
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 并将其 content/mime-type 提取为 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)
。您必须在文件 reader 的 onload
属性 中附加一个回调,并在回调被调用时解决一个承诺。我的意思是,而不是:
.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 类型,您只需从 blob 对象中读取属性 type
。
.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);
});
})
我在 Chrome 中使用 ServiceWorker 并使用 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() 正确检索它,而不是从网络请求它。但是如果我像这样使用 match() 方法:
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 传回。
我目前正在尝试 clone() 根据 this article 的响应,因为仅 return 通过 postMessage 获取完整响应将失败,抛出 DataCloneError:无法在 MessagePort 上执行 postMessage,我也没有找到很多相关信息。
如果我克隆,我可以调用 blob 给我一个新的(?)Blob,然后我可以传回它,但在尝试读取时只有 return 未定义:
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 并将其 content/mime-type 提取为 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)
。您必须在文件 reader 的 onload
属性 中附加一个回调,并在回调被调用时解决一个承诺。我的意思是,而不是:
.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 类型,您只需从 blob 对象中读取属性 type
。
.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);
});
})