Время, необходимое для того, чтобы данные в HTML LocalStorage были доступны в других окнах / вкладках
У меня есть веб-страница, которая использует HTML LocalStorage. Обычно несколько страниц / окон этой страницы открываются одновременно. Поскольку все они используют один и тот же LocalStorage, а LocalStorage не обеспечивает транзакции или аналогичные, я хотел бы реализовать некоторую форму взаимного исключения, чтобы не допустить неконтролируемой перезаписи данных различными вкладками / окнами.
Я попытался просто перенести свой тест алгоритма взаимного исключения Burns/Lynch на браузер, просто сохранив boolean[] F
в LocalStorage.
В FireFox все работает отлично, но Chrome допускает в среднем около 1,3 процессов (в основном только один, иногда два и очень редко даже 3 или более) в критическую секцию одновременно, а Internet Explorer позволяет в среднем 2 процесса (в основном 1, 2 или 3, иногда даже больше) в.
Поскольку алгоритм доказал свою корректность, а моя реализация очень тривиальна, и я протестировал его, в противном случае, единственная причина, по которой я могу придумать, почему это происходит, заключается в том, что в Chrome и IE есть задержка между тем, когда я пишу в LocalStorage в одной вкладке / окне, и когда новое значение будет видно во всех других вкладках / окнах.
Это возможно? Если да, есть ли какая-либо документация или есть гарантии на эти задержки? Или, что еще лучше, есть ли какой-нибудь вызов "commit"- или "flush()"- который я могу использовать для немедленного распространения изменений?
ОБНОВИТЬ:
Я собрал небольшую jsfiddle, чтобы проверить время прохождения туда-обратно:
// Get ID
var myID;
id = window.localStorage.getItem("id");
if (id==1) { myID = 1; window.localStorage.setItem("id", 0); }
else { myID = 0; window.localStorage.setItem("id", 1); }
// Initialize statistics variables
var lastrun = (new Date()).getTime();
var totaldelay = 0;
var count = 0;
var checks = 0;
document.documentElement.innerHTML = "ID: "+myID;
// Method that checks the round-trip time
function check() {
window.setTimeout(check, 1); // Keep running
value = window.localStorage.getItem("state");
checks++;
if (value==myID) return;
window.localStorage.setItem("state", myID);
now = new Date().getTime();
totaldelay += now - lastrun;
count++;
lastrun = now;
document.documentElement.innerHTML = "ID: "+myID+"<br/>"+
"Number of checks: "+checks+"<br/>"+
"Number of round-trips: "+count+"<br/>"+
"Checks per round-trip: "+checks/count+"<br/>"+
"Average round-trip time:"+totaldelay/count;
}
// Go!
window.setTimeout(check, 1000);
Если я запускаю эту скрипку в двух разных окнах, я получаю следующие числа во втором окне, которое я открыл:
Browser | Checks per round-trip | Average round-trip time
------------------+-----------------------+-------------------------
Firefox 24.3.0 | 1.00 | 6.1 ms
Chrome 46.0.2490 | 1.06 | 5.5 ms
IE 10 | 17.10 | 60.2 ms
1 ответ
Оказывается, Internet Explorer снова побеждает в конкурсе на худшее программное обеспечение, когда-либо написанное...
На самом деле существует серьезная ошибка в IE11 (и я вижу проблемы с IE10), которая в основном делает невозможным надежное использование LocalStorage, если пользователь открывает более одной вкладки: каждая вкладка, по сути, получает свою кешированную версию того же места хранения и синхронизация между этим кешем и фактическим хранилищем в лучшем случае ненадежна (если это вообще происходит). Нельзя вообще полагаться на данные, попадающие в другую вкладку / окно, в основном, когда-либо.
Вот официальный отчет об ошибке: IE 11 - Локальное хранилище - Проблемы с синхронизацией
(Что, естественно, является лишь одним из огромного списка других проблем с поддержкой LocalStorage в IE)
Мне нравится, как эта проблема была открыта в 2013 году и даже признана, но до сих пор не исправлена ...
К сожалению, ни один из трех опубликованных обходных путей не улучшил мои тесты.
Другими словами: кросс-таб / оконное взаимодействие с использованием LocalStorage в IE10/11 практически невозможно.
Удивительно, но синхронизация файлов cookie между окнами / вкладками выглядит намного стабильнее (по крайней мере, в моих тестах с IE10). Так что, может быть, это можно использовать в качестве обходного пути.