Руководство по использованию API магазина файлов cookie
29 апреля 2023 г.Сегодня, просматривая список веб-API на MDN, я наткнулся на один что меня удивило — API магазина файлов cookie. Это явно помечено как экспериментальное (в настоящее время поддерживается только в Chrome/Edge), но выглядит увлекательно.
Файлы cookie — это самый старый (насколько мне известно) способ для веб-приложений хранить данные на клиенте. Они также, как правило, являются наименее рекомендуемым способом сделать это по многим, многим причинам.
Однако иногда вам нужно работать с файлами cookie, и это выглядит как действительно хороший новый способ работы с ними. Вот краткий обзор.
Старый способ
В течение последних нескольких сотен лет работа с файлами cookie в браузере включала синтаксический анализ строк. На самом деле не было даже «API». Вы бы прочитали document.cookie
, который вернул строку значений cookie с разделителями:
'_ga=GA1.1.277504870.1615419234; ezux_ifep_238929=true; ezouspvh=1900; __qca=I0-1813545485-1623786777967; ezouspva=0; ezouspvv=0; ezux_et_238929=10099; ezux_tos_238929=5877205; _ALGOLIA=anonymous-c45533a4-0752-4b4d-90cb-b641b642cf4f; _ga_T5V3C8M5RY=GS1.1.1669062149.711.1.1669064843.0.0.0; hitCounter=0'
Чтобы получить конкретный файл cookie, вы должны проанализировать его с помощью точки с запятой, а затем разбить его на пары «имя-значение». Однако файлы cookie могут иметь больше, чем просто имя и значение. Например, у большинства файлов cookie есть срок действия. Но это не читается JavaScript.
Еще более странно то, что значение document.cookie
представляет собой список всех файлов cookie, которые вы можете использовать:
document.cookie = 'name=val';
Написать одну куки, оставив остальные в покое. При написании файлов cookie вы можете установить дополнительные значения, например срок действия, с помощью точки с запятой. Вот пример из MDN:
document.cookie =
"doSomethingOnlyOnce=true; expires=Fri, 31 Dec 9999 23:59:59 GMT; SameSite=None; Secure";
Из-за того, насколько это шатко, существуют библиотеки, чтобы упростить его. Раньше у MDN была хорошая небольшая библиотека для этого, но, к сожалению, похоже, она была удалена с их сайта.
К счастью, существует около десяти миллиардов других библиотек/утилит/простых функций JavaScript, которые вы могли бы использовать вместо этого. Или...
Блестящий новый путь
Итак, как я упоминал в начале, похоже, что у нас есть (или, надеюсь, будет) новый современный API для работы с файлами cookie. API магазина файлов cookie предоставляет асинхронный API для чтения, записи и удаления файлов cookie. Это также позволяет вам прослушивать изменения в файлах cookie.
Как упоминалось выше, в настоящее время это только совместимо с Chrome и Edge (хорошо , Опера и самсунг интернет тоже). Не знаю, добавит ли Safari это, и ваше предположение так же хорошо, как и мое.
Чтобы проверить наличие поддержки, вы можете найти объект cookieStorage
:
if(!("cookieStore" in window)) {
console.log('Not supported');
return;
}
После того как вы подтвердите, что можете использовать его, вот несколько кратких примеров методов.
Получение файла cookie
Чтобы получить файл cookie, используйте get
. Необычно, правда? Он поддерживает необязательную проверку области URL-адресов, обычно используемую на больших сайтах, чтобы ограничить доступность файла cookie только к его части. Вот самый простой пример:
let hitCounter = await cookieStore.get('hitCounter');
Как упоминалось ранее, API является асинхронным, поэтому вы можете либо ожидать
его, либо использовать затем
. Я предпочитаю await
.
Если файл cookie не существует, вы получите ответ null
; в противном случае такой объект:
{
"domain": null,
"expires": null,
"name": "hitCounter",
"path": "/",
"sameSite": "strict",
"secure": true,
"value": "7"
}
Обратите внимание, что значение является строкой. Вам нужно будет проанализировать его в своем коде, если вы хотите рассматривать его как число.
Настройка файла cookie
Как вы понимаете, настроить файл cookie также довольно просто. Если вы хотите установить файл cookie и значение, вы просто делаете:
cookieStore.set('hitCounter', 9);
Это также будет асинхронным, поэтому либо await
, либо обязательно используйте then
. Обратите внимание, что даже если я передам число, при сохранении оно станет строкой. Если вы хотите установить параметры, используйте форму:
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
cookieStore.set({
name:'hitCounter',
value:9,
expires:tomorrow
});
В этом примере я просто указал 24-часовую дату истечения срока действия в качестве опции, но есть и другие опции (проверьте set
docs для списка).
Удаление файла cookie
Опять же, еще один простой API, но помните, что он асинхронный:
cookieStore.delete('nameOfCookie');
Также есть такая опция, как get
, где вы можете передать объект, содержащий дополнительные параметры. Хорошим примером здесь может быть path
, и опять же, подумайте о большом веб-сайте, которому необходимо убедиться, что файл cookie с именем foo
в пути не мешает другому файлу cookie.
Cookie Monster (он же All the Cookies)
Последний метод, который я покажу, — это метод getAll
, который возвращает массив файлов cookie. Запуск cookieStore.getAll().then(console.log)
в моем блоге возвращает:
Прослушивание событий cookie
Одним из интересных аспектов API является возможность запускать код при изменении файлов cookie. Так, например:
cookieStore.onchange = (event) => {
console.log('cookie change event', event);
};
Это вызывает событие CookieChangeEvent. Это событие содержит несколько интересных свойств:
* type
сообщит вам тип изменения: удалено
или изменено
.
* changed
— это массив файлов cookie, которые были изменены.
* deleted
— это массив файлов cookie, которые были удалены.
В документах для события не указано, почему changed
и deleted
являются массивом, но если бы мне пришлось догадываться, из-за асинхронного характера API можно было бы изменить/удалить N файлов cookie, прежде чем событие сможет сработать в ответ; следовательно, нужны результаты в массиве.
Пример
Хотя в целом я бы не рекомендовал использовать файлы cookie для новых проектов, я сделал невероятно простую демонстрацию, которая отслеживает количество посещений вами сайта. Для этого используется файл cookie hitCounter
. Во-первых, HTML:
<h2>Cookie Store Demo 1</h2>
<p>
You have been to this page <span id="hitCount"></span> time(s).
</p>
А затем JavaScript:
document.addEventListener('DOMContentLoaded', init, false);
async function init() {
if(!("cookieStore" in window)) {
console.log('Not supported');
return;
}
cookieStore.onchange = (event) => {
console.log('cookie change event', event);
};
let hitCounter = await cookieStore.get('hitCounter');
if(!hitCounter) {
hitCounter = { value: 0 }
}
hitCounter.value = parseInt(hitCounter.value,10)+1;
try {
await cookieStore.set('hitCounter', hitCounter.value);
/*
const tomorrow = new Date();
tomorrow.setDate(tomorrow.getDate() + 1);
cookieStore.set({
name:'hitCounter',
value:hitCounter.value,
expires:tomorrow
});
*/
} catch(e) {
console.error(e);
}
document.querySelector('#hitCount').innerText = hitCounter.value;
}
По сути, прочитайте файл cookie, и, если он нулевой, по умолчанию будет равен 0. Затем добавьте к нему единицу после синтаксического анализа в целое число и сохраните значение. Теоретически мне не нужно await
; Я мог бы просто запустить и забыть и немедленно обновить DOM, но вы поняли идею.
Я также оставил в комментариях «только 24-часовую версию» просто для справки. Вы можете протестировать эту демонстрацию здесь: https://respected-periwinkle-warlock.glitch.me и просмотреть код здесь. : https://glitch.com/edit/#!/respected-periwinkle-warlock.< /p>
Прежде чем двигаться дальше, краткое примечание о try/catch
. Браузер может блокировать запись в куки, и если это так, вы получите сообщение об ошибке:
Error: An unknown error occurred while writing the cookie.
Если вы заботитесь об этом в своем приложении, обратите внимание на ошибку.
Оригинал