从 service worker 访问 localStorage

Posted

技术标签:

【中文标题】从 service worker 访问 localStorage【英文标题】:Access localStorage from service worker 【发布时间】:2017-04-14 17:35:46 【问题描述】:

我想定期从我的 Service Worker 调用 API 以发送存储在 localStorage 中的数据。当用户浏览我的网站时,这些数据将被生成并保存在localStorage。将其视为将统计信息保存在localStorage 并通过服务人员定期发送。我该怎么做?我知道我无法从服务人员访问localStorage,必须使用postMessage API。任何帮助将不胜感激。

【问题讨论】:

即使这个问题提到了角度,它也包含一个可能的答案:***.com/questions/52721826/… @Faiz 你找到解决办法了吗? 【参考方案1】:

广播频道 API 更简单

有several ways 用于客户端和控制服务工作者之间的通信,但localStorage 不是其中之一。 IndexedDB 是, 但这对于无论如何都应该保持苗条的 PWA 来说可能有点过头了。

无论如何,Broadcast Channel API 结果最简单。它比上面提到的postMessage() 和MessageChannel API 更容易实现。

这是广播的工作原理

在服务工作者和客户端中定义一个新的广播频道。

const channel4Broadcast = new BroadcastChannel('channel4');

要在工作人员或客户端中发送广播消息:

channel4Broadcast.postMessage(key: value);

要在工作人员或客户端中接收广播消息:

channel4Broadcast.onmessage = (event) => 
    value = event.data.key;

【讨论】:

非常干净。直截了当,没有太多花里胡哨和解决方法 最好的方法【参考方案2】:

我自己为一个小型 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 将新值保存到后端,一旦用户上线。 这不会让 Service Worker 访问 localStorage,但会向他发送所做的所有更改。

刚刚开始习惯这个同步主题。所以我真的很感兴趣,无论这是否有帮助以及其他人对此解决方案的看法。

【讨论】:

IMO - 同步并不总是可用(浏览器支持并且用户可以禁用它),此外这看起来过于复杂 - 为什么不简单地发送消息? navigator.serviceWorker.controller.postMessage( value:'...' , [new MessageChannel().port2]);【参考方案3】:

我一直在使用这个名为 localforage 的包,它提供了一个类似于 localStorage 的接口,它围绕着 IndexedDB。 https://github.com/localForage/localForage

然后,您可以通过将其放置在您的公共目录中来导入它,以便由您的网络服务器提供服务,然后在您的服务人员中调用:self.importScripts('localforage.js');

【讨论】:

IndexedDB 在 Service Worker 中工作——这就是 LocalForage 工作的原因(它默认为 IndexedDB)。这个问题是关于 LocalStorage 的,Service Workers 无法访问它 @Robert Question 说“我知道我无法访问 localStorage...任何帮助将不胜感激。” 尽管此答案不包括使用 localStorage 的解决方案,但它提供了一个极好的替代方案,易于实现并保持用户熟悉的类似语法。我已经尝试过这个解决方案,它是一个非常容易实现和从本地存储迁移的方法。【参考方案4】:

您不能从 webworker 进程访问 localStorage(以及 sessionStorage),它们的结果将是 undefined,这是出于安全原因。

您需要使用postMessage() 回到 Worker 的原始代码,并让该代码将数据存储在 localStorage 中。

您应该使用localStorage.setItem()localStorage.getItem() 从本地存储中保存和获取数据。

更多信息:

Worker.postMessage()

Window.localStorage

下面的伪代码,希望它能让你开始:

 // 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)

【讨论】:

var myWorker = new YourWorker('YourWorker.js'), > new WebWorker 对吧? @Roberrrt 感谢您的评论,正确的是new Worker() :) 感谢 GibboK,但我有几个疑问。您提到的代码将在我的一个 javascript 中运行。为了运行这个用户必须让网站运行?不是吗?我正在寻找服务工作者定期从本地存储发送数据的东西,即使用户不在我的网站上也是如此。我的情况甚至可能吗? @Faiz 如果您认为我的回答对您有所帮助,请不要忘记点击左侧 V 图标接受它。感谢和愉快的编码:) @FelipeMorales afik 它应该也适用于服务工作者与网页的通信必须通过服务工作者 PostMessage 方法。但请试一试,让我们知道:)【参考方案5】:

https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers 说

注意:localStorage 的工作方式与 Service Worker 缓存类似,但它是同步的,因此不允许在 Service Worker 中使用。

注意:如果需要,可以在 Service Worker 内部使用 IndexedDB 进行数据存储。

这里也有一点讨论:How do I access the local storage using service workers in angular?

【讨论】:

以上是关于从 service worker 访问 localStorage的主要内容,如果未能解决你的问题,请参考以下文章

Service worker 简介

认识 service worker

使用Service Worker和离线缓存Cache

Service Worker基础知识整理

Nginx修改静态文件访问路径

Service Worker概念和应用介绍