LocalStorage не обновляется во время блока оповещения - PullRequest
1 голос
/ 25 июня 2019

Сегодня я боролся со странным поведением с локальным хранилищем, которое я сломал до простого сценария.Похоже, что браузер Chrome не синхронизирует localStorage, если во время записи значения отображается окно предупреждения.

Открыты 2 вкладки браузера.

Tab A запрашивает файл read.html :

    var item = localStorage.getItem('test');
    console.log('item before alert', item);

    alert('Pause!'); // don't close it before calling write.html

    item = localStorage.getItem('test');
    console.log('item after alert', item);

Окно предупреждения с надписью "Пауза!"не будет закрыт.

Другая вкладка B запрашивает файл write.html :

    var item = (localStorage.getItem('test') || '') + 'a';
    console.log('new item:', item);
    localStorage.setItem('test', item);

Вы можете видеть, что значение было обновлено в localStorage вбраузеры (Chrome) Devtools, но только в одном из Tab B .

Это происходит только в Chrome.IE11 и Firefox работают как положено.У кого-нибудь есть подсказка, если это по замыслу или ошибка в Chrome?

С уважением, Маркус

Редактировать: Создан проект github с кодом: https://github.com/wondee/localStorage-bug

Обновление: После ответа Артемса я попытался дождаться отправки, и это действительно помогло с помощью следующего кода, добавленного в read.html после последнего console.log(..), изменения корректно отображаются:

setTimeout(() => console.log('item after 1s:', localStorage.getItem('test')), 1);

Ответы [ 2 ]

1 голос
/ 25 июня 2019

Согласно спецификации (прочитайте ее до конца, чтобы охватить возможные вопросы).

Когда методы setItem (), removeItem () и clear () вызываются для объекта Storage x, который связан с локальной областью хранения, если методы не генерируют исключение или «ничего не делают», как определено выше затем для каждого объекта Document, чей объект хранения атрибута localStorage соответствующего глобального объекта связан с той же областью хранения, кроме x, отправляет уведомление хранения .

В принципе, насколько я понимаю, когда пользователь открывает новую вкладку с тем же происхождением, создается копия хранилища . Поэтому при изменении хранилища на одной вкладке - событие хранилища отправляется ( задача ставится в очередь ) на все остальные вкладки (для того же источника) для их синхронизации.

Когда пользовательский агент должен отправить уведомление о хранении для документа, пользовательский агент должен поставить задачу в очередь, чтобы запустить событие с именем storage в соответствующем глобальном объекте объекта Document, используя StorageEvent.

Но в вашем конкретном случае из-за синхронного alert() цикл обработки событий не может получить это событие в очереди, пока ваш сценарий не будет завершен и стек вызовов не будет пустым.

Но как только ваш скрипт на первой вкладке будет завершен, цикл обработки событий обнаружит это событие и отразит изменения в своей копии хранилища.

Но в спецификации есть четкое предупреждение о том, что вам следует избегать обновления того же общего состояния, как вы делаете это в своем примере, так как нет механизма блокировки.

Внимание! Атрибут localStorage обеспечивает доступ к общему состоянию. Эта спецификация не определяет взаимодействие с другими контекстами просмотра в многопроцессорном пользовательском агенте, и авторам предлагается предположить, что механизм блокировки отсутствует. Например, сайт может попытаться прочитать значение ключа, увеличить его значение, а затем записать его обратно, используя новое значение в качестве уникального идентификатора для сеанса; если сайт делает это дважды в двух разных окнах браузера одновременно, он может в конечном итоге использовать один и тот же «уникальный» идентификатор для обоих сеансов, что может иметь катастрофические последствия.

0 голосов
/ 25 июня 2019

Вы пытались очистить localStorage перед установкой нового значения?попробуйте

localStorage.removeItem('test');
localStorage.setItem('test',item);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...