我想定期从我的服务工作者调用API来发送存储在localStorage中的数据。当用户浏览我的网站时,将生成此数据并将其保存在localStorage中。考虑一下像在localStorage中保存统计信息并定期通过服务工作者发送它。我该怎么做?我知道我无法从服务工作者访问localStorage,并且必须使用postMessage API。任何帮助都将受到高度赞赏。
答案 0 :(得分:8)
您无法从webworker进程访问localStorage(以及sessionStorage),结果将是undefined
,这是出于安全原因。
您需要使用postMessage()
回到Worker的原始代码,并让该代码将数据存储在localStorage中。
您应该使用localStorage.setItem()
和localStorage.getItem()
来保存并从本地存储中获取数据。
更多信息:
下面的伪代码,希望它能帮到你:
// include your worker
var myWorker = new Worker('YourWorker.js'),
data,
changeData = function() {
// save data to local storage
localStorage.setItem('data', (new Date).getTime().toString());
// get data from local storage
data = localStorage.getItem('data');
sendToWorker();
},
sendToWorker = function() {
// send data to your worker
myWorker.postMessage({
data: data
});
};
setInterval(changeData, 1000)
答案 1 :(得分:2)
我一直在使用名为localforage
的程序包,该程序包提供了一个类似于LocalStorage的接口,该接口包装了IndexedDB。 https://github.com/localForage/localForage
然后可以通过将其放置在公共目录中来导入它,以便由Web服务器为其提供服务,然后在服务工作者中调用:self.importScripts('localforage.js');
。
答案 2 :(得分:1)
我自己为一个小型的Webapp项目遇到了这个问题,我考虑了以下解决方案:
当用户在线时,可以立即发送数据。当他离线时,我使用SyncEvent.tag
属性将信息从客户端发送到服务工作人员。像这样:
//offline_page.html (loads only, when user is offline)
button.onclick = function() {
//on click: store new value in localStorage and prepare new value for synchronization
localStorage.setItem("actual", numberField.value);
navigator.serviceWorker.ready.then(function(swRegistration) {
return swRegistration.sync.register('newval:'+numberField.value);
});
}
//sw.js
self.addEventListener('sync', function(event) {
//let's say everything in front of ':' is the option, everything afterwards is the value
let option = event.tag.replace(/(.*?)\:.*?$/, "$1");
let value = event.tag.replace(/.*?\:(.*?)$/, "$1");
if(option == "newval") {
event.waitUntil(
fetch("update.php?newval="+value)
.then(function(response) {
console.log(response);
})
);
}
});
用户上线后, update.php
会将新值保存到后端。
这不会使服务人员可以访问localStorage,但会将所做的所有更改发送给他。
刚刚开始习惯这个同步主题。因此,我真的很感兴趣,这对您有所帮助,以及其他人对此解决方案的看法。
答案 3 :(得分:0)
https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers说
注意:localStorage的工作方式与服务工作者缓存类似,但是它是同步的,因此服务工作者中不允许这样做。
注意:如果需要,可以在Service Worker中使用IndexedDB进行数据存储。
这里也有一些讨论:How do I access the local storage using service workers in angular?
答案 4 :(得分:0)
有 several ways 用于在客户端和控制 Service Worker 之间进行通信,但 localStorage
不是其中之一。
IndexedDB
是,,但这对于无论如何都应该保持苗条的 PWA 来说可能是一种矫枉过正。
总之,Broadcast Channel API 的结果最简单。到目前为止,使用 MessageChannel API 实现比上述 postMessage()
容易得多。
在 Service Worker 和客户端中定义一个新的广播频道。
const channel4Broadcast = new BroadcastChannel('channel4');
要在工作程序或客户端中发送广播消息:
channel4Broadcast.postMessage({key: value});
要在工作程序或客户端接收广播消息:
channel4Broadcast.onmessage = (event) => {
value = event.data.key;
}