Главная » Статьи » Обработка битых изображений с помощью Service Worker

Обработка битых изображений с помощью Service Worker

Обработка битых изображений с помощью Service Worker

От автора: несколько лет назад я писала о том, как мы можем использовать CSS для стилизации битых изображений. Техника основана на том факте, что любые стили псевдо-элементов ::before или ::after для элемента будут применяться только в том случае, если изображение не загружается. Таким образом, мы можем стилизовать эти элементы, и они будут отображаться, только если изображение было повреждено.

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

Недавно, когда мне пришлось плотно работать с Service Worker, мне пришло в голову, что мы можем использовать их для обработки битых изображений другим способом. Так как Service Worker может определить, удалось ли получить файл изображения, в противном случае мы можем, например, предоставить браузеру другое изображение.

Перехват запросов на битые изображения

В событии Service Worker fetch мы можем определить, когда в запросе, выполненном браузером, что-то пошло не так, будь то из-за того, что пользователь был оффлайн или ответ на запрос был неверным.

self.addEventListener('fetch', (e) => { e.respondWith( fetch(e.request) .then((response) => { if (response.ok) return response; // Пользователь онлайн, но ответ не в порядке }) .catch((err) => { // Пользователь, вероятно, оффлайн }) )
});

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

function isImage(fetchRequest) { return fetchRequest.method === "GET" && fetchRequest.destination === "image";
} self.addEventListener('fetch', (e) => { e.respondWith( fetch(e.request) .then((response) => { if (response.ok) return response; // Пользователь онлайн, но ответ не в порядке if (isImage(e.request)) { // делаем что-то } }) .catch((err) => { // Пользователь, вероятно, оффлайн if (isImage(e.request)) { // делаем что-то } }) )
});

Обслуживание изображения «битого изображения»

Одним из способов обработки запросов на изображения, которые не разрешаются, является отправка на его место изображения-заполнителя. Например, у нас может быть изображение, подобное приведенному ниже, чтобы показать пользователю, что изображение повреждено.

Мы можем осуществить это, отвечая на запрос fetch новым запросом на файл заполнителя, /broken.png.

self.addEventListener('fetch', (e) => { e.respondWith( fetch(e.request) .then((response) => { if (response.ok) return response; // Пользователь онлайн, но ответ не в порядке if (isImage(e.request)) { // Извлекаем вместо этого заполнитель битого изображения return fetch("/broken.png"); } }) .catch((err) => { // Пользователь, вероятно, оффлайн if (isImage(e.request)) { // делаем что-то } }) // конец fetch )
});

Это будет работать, когда пользователь находится в сети, но если мы хотим, чтобы это также работало в автономном режиме, нам нужно будет кэшировать изображение заполнителя. Обычно это делается на этапе жизненного цикла service worker install.

self.addEventListener('install', (e) => { self.skipWaiting(); e.waitUntil( caches.open("precache").then((cache) => { // Добавляем /broken.png в "precache" cache.add("/broken.png"); }) );
});

Когда изображение помещено в кэш, мы можем ответить на запрос fetch ответом из кеша, вместо того, чтобы выполнять новый запрос к сети.

self.addEventListener('fetch', (e) => { e.respondWith( fetch(e.request) .then((response) => { if (response.ok) return response; // Пользователь онлайн, но ответ не в порядке if (isImage(e.request)) { // Получаем из кэша изображение-заполнитель return caches.match("/broken.png"); } }) .catch((err) => { // Пользователь, вероятно, оффлайн if (isImage(e.request)) { // Получаем из кэша изображение-заполнитель return caches.match("/broken.png"); } }) )
});

Я создал GitHub Gist с полной реализацией на случай, если вы захотите использовать его в своих собственных проектах.

Источник: https://bitsofco.de/

Редакция: Команда webformyself.