service worker app-shell PHP 实现
service worker app-shell PHP implementation
我在我的 site.And 上引入了 service worker 我正在使用 app-shell 方法来响应 requests.Below 是我的代码结构。
serviceWorker.js
self.addEventListener("fetch", function(event) {
if (requestUri.indexOf('-spid-') !== -1) {
reponsePdPage(event,requestUri);
}else{
event.respondWith(fetch(requestUri,{mode: 'no-cors'}).catch(function (error){
console.log("error in fetching => "+error);
return new Response("not found");
})
);
}
});
function reponsePdPage(event,requestUri){
var appShellResponse=appShellPro();
event.respondWith(appShellResponse); //responds with app-shell
event.waitUntil(
apiResponse(requestUri) //responds with dynamic content
);
}
function appShellPro(){
return fetch(app-shell.html);
}
function apiResponse(requestUri){
var message=['price':'12.45cr'];
self.clients.matchAll().then(function(clients){
clients.forEach(function (client) {
if(client.url == requestUri)
client.postMessage(JSON.stringify(message));
});
});
}
应用-shell.html
<html>
<head>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.onmessage = function (evt) {
var message = JSON.parse(evt.data);
document.getElementById('price').innerHTML=message['price'];
}
}
</script>
</head>
<body>
<div id="price"></div>
</body>
</html>
serviceWorker.js 是我唯一的 service worker 文件。每当我在 url 中收到 -spid- 请求时,我都会调用 reponsePdPage function.In reponsePdPage 函数,我首先响应 app-shell.html。之后我调用 apiResponse 函数调用 post 消息并发送动态 data.The listener of post message写在app-shell.html.
我面临的问题是,有时 post 消息在侦听器 registration.It 之前被调用意味着 apiResponse 调用 post 消息但他们没有注册该事件的侦听器。所以我无法捕获数据。是他们在我的实现中出了什么问题吗?
我只关注最后一点,关于 service worker 和受控页面之间的通信。该问题与您提供的许多其他详细信息是分开的,例如使用 PHP 和采用 App Shell 模型。
如您所见,存在竞争条件,因为 service worker 中的代码和 HTML 的解析和执行是在不同的进程中执行的。当服务人员调用 client.postMessage()
.
时,onmessage
处理程序尚未在页面中建立,我对此并不感到惊讶。
如果您想将信息从 service worker 传递到受控页面,同时避免竞争条件,您有几个选择。
第一个可能也是最简单的选项是更改通信方向,并让受控页面使用 postMessage()
向 service worker 发送请求,然后 service worker 以相同的信息进行响应。如果您采用这种方法,您将确保受控页面已准备好接受 service worker 的响应。有一个完整的示例 here,但这里有一个相关位的简化版本,它使用基于 Promise 的包装器来处理从 service worker 收到的异步响应:
受控页面内:
function sendMessage(message) {
// Return a promise that will eventually resolve with the response.
return new Promise(function(resolve) {
var messageChannel = new MessageChannel();
messageChannel.port1.onmessage = function(event) {
resolve(event.data);
};
navigator.serviceWorker.controller.postMessage(message,
[messageChannel.port2]);
});
}
Service Worker 内部:
self.addEventListener('message', function(event) {
// Check event.data to see what the message was.
// Put your response in responseMessage, then send it back:
event.ports[0].postMessage(responseMessage);
});
其他方法包括在服务工作者内部的 IndexedDB 中设置一个值,然后在加载后从受控页面读取该值。
最后,您实际上可以获取从缓存存储 API 中检索到的 HTML,将其转换为字符串,修改该字符串以内嵌相关信息,然后响应包含修改后的 HTML 的新 Response
。不过,这可能是最重量级和最脆弱的方法。
我在我的 site.And 上引入了 service worker 我正在使用 app-shell 方法来响应 requests.Below 是我的代码结构。
serviceWorker.js
self.addEventListener("fetch", function(event) {
if (requestUri.indexOf('-spid-') !== -1) {
reponsePdPage(event,requestUri);
}else{
event.respondWith(fetch(requestUri,{mode: 'no-cors'}).catch(function (error){
console.log("error in fetching => "+error);
return new Response("not found");
})
);
}
});
function reponsePdPage(event,requestUri){
var appShellResponse=appShellPro();
event.respondWith(appShellResponse); //responds with app-shell
event.waitUntil(
apiResponse(requestUri) //responds with dynamic content
);
}
function appShellPro(){
return fetch(app-shell.html);
}
function apiResponse(requestUri){
var message=['price':'12.45cr'];
self.clients.matchAll().then(function(clients){
clients.forEach(function (client) {
if(client.url == requestUri)
client.postMessage(JSON.stringify(message));
});
});
}
应用-shell.html
<html>
<head>
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.onmessage = function (evt) {
var message = JSON.parse(evt.data);
document.getElementById('price').innerHTML=message['price'];
}
}
</script>
</head>
<body>
<div id="price"></div>
</body>
</html>
serviceWorker.js 是我唯一的 service worker 文件。每当我在 url 中收到 -spid- 请求时,我都会调用 reponsePdPage function.In reponsePdPage 函数,我首先响应 app-shell.html。之后我调用 apiResponse 函数调用 post 消息并发送动态 data.The listener of post message写在app-shell.html.
我面临的问题是,有时 post 消息在侦听器 registration.It 之前被调用意味着 apiResponse 调用 post 消息但他们没有注册该事件的侦听器。所以我无法捕获数据。是他们在我的实现中出了什么问题吗?
我只关注最后一点,关于 service worker 和受控页面之间的通信。该问题与您提供的许多其他详细信息是分开的,例如使用 PHP 和采用 App Shell 模型。
如您所见,存在竞争条件,因为 service worker 中的代码和 HTML 的解析和执行是在不同的进程中执行的。当服务人员调用 client.postMessage()
.
onmessage
处理程序尚未在页面中建立,我对此并不感到惊讶。
如果您想将信息从 service worker 传递到受控页面,同时避免竞争条件,您有几个选择。
第一个可能也是最简单的选项是更改通信方向,并让受控页面使用 postMessage()
向 service worker 发送请求,然后 service worker 以相同的信息进行响应。如果您采用这种方法,您将确保受控页面已准备好接受 service worker 的响应。有一个完整的示例 here,但这里有一个相关位的简化版本,它使用基于 Promise 的包装器来处理从 service worker 收到的异步响应:
受控页面内:
function sendMessage(message) {
// Return a promise that will eventually resolve with the response.
return new Promise(function(resolve) {
var messageChannel = new MessageChannel();
messageChannel.port1.onmessage = function(event) {
resolve(event.data);
};
navigator.serviceWorker.controller.postMessage(message,
[messageChannel.port2]);
});
}
Service Worker 内部:
self.addEventListener('message', function(event) {
// Check event.data to see what the message was.
// Put your response in responseMessage, then send it back:
event.ports[0].postMessage(responseMessage);
});
其他方法包括在服务工作者内部的 IndexedDB 中设置一个值,然后在加载后从受控页面读取该值。
最后,您实际上可以获取从缓存存储 API 中检索到的 HTML,将其转换为字符串,修改该字符串以内嵌相关信息,然后响应包含修改后的 HTML 的新 Response
。不过,这可能是最重量级和最脆弱的方法。