С помощью двунаправленных каналов сервисных работников (MessageChannel / postMessage) можно «сохранить» значение переменной javascript в глобальной области видимости сервисного работника между перезагрузками страниц, навигацией, нажатиями кнопок назад / вперед (это также работает черезвкладки, но мне все равно):
//query data
send_message_to_sw("").then(function(response) {
var data;
if (response) {
//restore data
data = response;
} else {
data = confirm("the button you choose will be remembered for some time, but sometimes you'll have to click again") ? "left" : "right";
//Store data
send_message_to_sw(data)
}
alert("data: " + data);
return data;
});
Хотя срок службы сервисных работников должен быть очень коротким и его глобальная область действия часто сбрасывается, в Firefox 61 я вижу, что глобальный масштаб работника сервисной службы сохраняет данные нетронутыми (полный код доступен в конце вопроса).
Вопросы:
1) Есть ли способ гарантировать, что глобальная область работника службы не будет сброшена?Работник службы ничего не делает, но хранит несколько сотен байтов в своей глобальной области (без продолжительных вычислений, без извлечения, без зависания).
2) Для перезагрузки страницы, как этот метод сравнивается с установкойзначение скрытого поля.Есть ли у него меньше или больше гарантий?И на практике, вы получаете такое же поведение?(Я думаю, что установка значения скрытого поля не сохраняется на диске, но я не уверен)
3) Каковы другие альтернативы этой технике?Я пытаюсь хранить очень конфиденциальные данные (криптографический закрытый ключ: никогда не следует записывать на диск; его можно восстановить, попросив пользователя повторно ввести свой пароль, но для удобства следует запомнить его "на некоторое время") при перезагрузке страницы илинавигация.
КОД:
app.js
function send_message_to_sw(msg){
return new Promise(function(resolve, reject){
// Create a Message Channel
var msg_chan = new MessageChannel();
// Handler for recieving message reply from service worker
msg_chan.port1.onmessage = function(event){
if(event.data.error){
reject(event.data.error);
}else{
resolve(event.data);
}
};
// Send message to service worker along with port for reply
navigator.serviceWorker.controller.postMessage(msg, [msg_chan.port2]);
});
}
sw.js
self.addEventListener('message', function(event){
if (event.data !== "") {
self.GLOBALDATA = event.data;
}
event.ports[0].postMessage(self.GLOBALDATA||"");
});