Веб-платформа и API
API браузерной платформы — fetch и XHR, клиентское хранилище и IndexedDB, web- и service-воркеры, postMessage, server-sent events и PWA.
12 вопросов
JuniorТеорияОчень частоЧто возвращает fetch() и как прочитать JSON из ответа?
Что возвращает fetch() и как прочитать JSON из ответа?
fetch(url) возвращает Promise, который разрешается объектом Response, как только пришли заголовки, а не тело. Тело читается ещё одним методом-промисом, например response.json() или response.text(). Поэтому обычно пишут цепочку fetch(url).then(r => r.json()).then(data => ...) или используют await. Свойство response.ok показывает, был ли статус 2xx.
Типичные ошибки
- ✗Думать, что промис
fetchразрешается телом — он разрешается объектомResponse, тело нужно читать отдельно - ✗Считать
response.json()синхронным — он возвращает промис, который надо ждать - ✗Забывать, что
fetchразрешается по приходу заголовков, до загрузки тела
Уточняющие вопросы
- →Почему
response.json()сам возвращает промис, а не разобранное значение? - →Что произойдёт, если вызвать
response.json()дважды на одном ответе?
JuniorТеорияЧастоЧем различаются localStorage, sessionStorage и IndexedDB как клиентское хранилище?
Чем различаются localStorage, sessionStorage и IndexedDB как клиентское хранилище?
localStorage и sessionStorage — синхронные хранилища ключ/значение только для строк (~5МБ), привязанные к origin. localStorage хранится до очистки; sessionStorage живёт лишь в рамках сессии вкладки. IndexedDB — асинхронная транзакционная база для больших структурированных данных, включая объекты и blob. Событие storage срабатывает в других вкладках того же origin при изменении localStorage, позволяя им синхронизироваться.
Типичные ошибки
- ✗Думать, что web storage хранит объекты напрямую — значения приводятся к строкам
- ✗Считать, что событие
storageсрабатывает во вкладке, сделавшей изменение - ✗Путать
sessionStorage(на вкладку) сlocalStorage(постоянный, на origin)
Уточняющие вопросы
- →Почему
localStorage.setItem('k', {a:1})сохраняет буквально[object Object]? - →Когда IndexedDB предпочтительнее web storage?
JuniorТеорияИногдаЧто такое XMLHttpRequest и что отслеживает его readyState?
Что такое XMLHttpRequest и что отслеживает его readyState?
XMLHttpRequest (XHR) — классический API для HTTP-запросов из JavaScript, основа AJAX. Вы вызываете open(method, url, async), затем send(). По умолчанию async равен true, поэтому вызов неблокирующий и результат обрабатывается в колбэке onreadystatechange. readyState проходит 0→4 по жизненному циклу запроса; 4 означает готово, после чего проверяют status.
Типичные ошибки
- ✗Считать XHR синхронным по умолчанию —
asyncравенtrue, пока вы не отключите его - ✗Путать
readyState(этап жизненного цикла) соstatus(HTTP-кодом) - ✗Думать, что XHR несёт только XML, тогда как он работает с JSON, текстом и бинарными данными
Уточняющие вопросы
- →Почему синхронный XHR (
asyncравныйfalse) не рекомендуют в главном потоке? - →Как
fetchулучшает работу с жизненным циклом запроса по сравнению с XHR?
JuniorТеорияИногдаДля чего нужен window.postMessage и почему надо проверять origin сообщения?
Для чего нужен window.postMessage и почему надо проверять origin сообщения?
window.postMessage позволяет скриптам в разных окнах или iframe общаться между origin, безопасно обходя политику одного источника. Отправитель вызывает target.postMessage(data, targetOrigin); получатель слушает событие message. В обработчике надо проверять event.origin (а лучше и event.source), ведь написать вам может любая страница — доверие к непроверенным сообщениям открывает дыру XSS. Избегайте подстановки * в цели.
Типичные ошибки
- ✗Пропускать проверку
event.origin, доверяя любому пришедшему сообщению - ✗Ставить
*как целевой origin, раскрывая данные любому origin - ✗Думать, что недоверенных отправителей отсеивает браузер, а не ваш обработчик
Уточняющие вопросы
- →Почему передача
*как целевого origin — риск безопасности для отправителя? - →Как проверка
event.sourceдобавляет защиту сверхevent.origin?
JuniorТеорияИногдаЧто такое Web Worker и почему он не может обращаться к DOM?
Что такое Web Worker и почему он не может обращаться к DOM?
Web Worker выполняет скрипт в отдельном фоновом потоке, поэтому тяжёлая работа не блокирует главный поток UI. У него нет доступа к DOM, window или родительскому document, ведь они не потокобезопасны и принадлежат только главному потоку. Воркер и страница общаются обменом сообщениями через postMessage, а не прямым доступом к объектам страницы.
Типичные ошибки
- ✗Пытаться читать или менять DOM внутри воркера — он там недоступен
- ✗Полагать, что воркер делит переменные страницы, а не общается сообщениями
- ✗Считать, что воркер работает в главном потоке, поэтому не распараллеливает
Уточняющие вопросы
- →Какие глобальные объекты (например
selfилиfetch) всё же доступны воркеру? - →Как воркер передаёт обновление DOM обратно главному потоку для выполнения?
MiddleТеорияИногдаЧем fetch лучше XHR и почему он не отклоняется при 404?
Чем fetch лучше XHR и почему он не отклоняется при 404?
fetch основан на промисах, поэтому сочетается с async/await вместо колбэков XHR и даёт потоковое response.body. Важно, что его промис отклоняется только при сетевом сбое — HTTP 404 или 500 всё равно разрешаются, поэтому статус надо проверять самому через response.ok или response.status. Отмена не встроена; вы передаёте signal из AbortController и вызываете controller.abort().
Типичные ошибки
- ✗Ждать, что
fetchотклонится при 404 или 500 — отклоняются лишь сетевые ошибки - ✗Забывать проверить
response.okперед чтением тела - ✗Думать, что fetch нельзя отменить — сигнал даёт
AbortController
Уточняющие вопросы
- →Как одним сигналом
AbortControllerотменить сразу несколько fetch-запросов? - →Как обернуть
fetch, чтобы не-okответы отклонялись, какonerrorв XHR?
MiddleТеорияИногдаКаков жизненный цикл service worker и как он обеспечивает офлайн?
Каков жизненный цикл service worker и как он обеспечивает офлайн?
Service worker — фоновый скрипт, работающий как сетевой прокси между страницей и сетью. Он проходит install (предзагрузка ресурсов), activate (очистка старых кэшей), затем fetch, где перехватывает запросы и может отвечать из Cache API для офлайна. У него нет доступа к DOM, он событийный, завершается при простое и перезапускается по требованию, поэтому состояние должно жить в IndexedDB или кэше, а не в глобальных переменных.
Типичные ошибки
- ✗Хранить состояние в глобальных переменных воркера — он завершается при простое и перезапускается
- ✗Думать, что service worker может напрямую читать или менять DOM
- ✗Считать, что офлайн работает без перехвата
fetchи ответа из кэша
Уточняющие вопросы
- →Почему service worker должен хранить состояние в IndexedDB, а не в глобальных переменных?
- →В чём разница между событиями
installиactivate?
MiddleТеорияИногдаКак страница и Web Worker обмениваются данными и что такое Transferable-объекты?
Как страница и Web Worker обмениваются данными и что такое Transferable-объекты?
Они общаются передачей сообщений: каждая сторона вызывает postMessage(data) и слушает через onmessage. Данные копируются алгоритмом structured clone, поэтому воркер получает независимую копию — без общих ссылок. Для крупных буферов копирование дорого, поэтому передают Transferable-объекты (например ArrayBuffer) вторым аргументом; владение переходит к получателю без копирования, а ссылка отправителя становится непригодной.
Типичные ошибки
- ✗Полагать, что
postMessageделит ссылку, а не копию structured clone - ✗Думать, что отправитель сохраняет пригодный буфер после передачи Transferable
- ✗Считать, что сообщения ограничены JSON-сериализуемыми обычными объектами
Уточняющие вопросы
- →Почему передача
ArrayBufferбыстрее, чем копирование его через structured clone? - →Что произойдёт, если прочитать буфер отправителя после его передачи?
MiddleТеорияРедкоЧто за хранилище IndexedDB и когда оно предпочтительнее web storage?
Что за хранилище IndexedDB и когда оно предпочтительнее web storage?
IndexedDB — асинхронная транзакционная объектная клиентская база для больших объёмов структурированных данных. Все чтения и записи идут через транзакции и завершаются через события или промисы, не блокируя поток. Она хранит значения по structured-clone — объекты, массивы, blob, а не только строки, и поддерживает индексы для быстрых запросов. Предпочитайте её web storage для крупных датасетов, асинхронного доступа (например из воркера) или запрашиваемых записей.
Типичные ошибки
- ✗Считать IndexedDB синхронным — каждая операция асинхронна через события или промисы
- ✗Думать, что оно хранит только строки, тогда как оно держит structured-clone объекты и blob
- ✗Забывать, что весь доступ идёт внутри транзакций
Уточняющие вопросы
- →Почему IndexedDB можно использовать в воркере, а
localStorage— нет? - →Какие типы умеет сериализовать structured clone, а
JSON.stringify— нет?
MiddleТеорияРедкоЧто такое server-sent events через EventSource и чем они отличаются от WebSocket?
Что такое server-sent events через EventSource и чем они отличаются от WebSocket?
Server-sent events позволяют серверу слать обновления в браузер по одному долгоживущему HTTP-соединению. Клиент открывает new EventSource(url) и обрабатывает onmessage/onopen/onerror; канал односторонний, сервер→клиент, только текст. Браузер автоматически переподключается при обрыве и может возобновиться через Last-Event-ID. WebSocket же — отдельный полнодуплексный протокол, несущий бинарные и текстовые данные в обе стороны.
Типичные ошибки
- ✗Думать, что SSE двунаправленный — он односторонний, только сервер→клиент
- ✗Писать ручное переподключение, когда
EventSourceпереподключается сам - ✗Ждать от SSE бинарных кадров, тогда как он только текстовый
Уточняющие вопросы
- →Как заголовок
Last-Event-IDпозволяет переподключённому клиенту возобновить поток? - →Когда для функции вы выберете WebSocket вместо SSE?
SeniorТеорияРедкоКакие части делают Progressive Web App офлайн-способным и устанавливаемым?
Какие части делают Progressive Web App офлайн-способным и устанавливаемым?
PWA — это сайт, ведущий себя как установленное приложение. Ключевые части: service worker, перехватывающий fetch и отдающий кэш для офлайна; Cache API и IndexedDB для оболочки приложения и данных; web app manifest (имя, иконки, display, start_url), делающий приложение устанавливаемым на главный экран. Стратегия offline-first кэширует оболочку на install, затем мгновенно отдаёт её, обновляя в фоне.
Типичные ошибки
- ✗Думать, что офлайн обеспечивает manifest, а не service worker
- ✗Считать, что офлайн включается сам, как только сайт на HTTPS
- ✗Забывать, что оболочку надо предкэшировать на
installдля мгновенной офлайн-загрузки
Уточняющие вопросы
- →Как стратегия cache-first для оболочки продолжает обновлять контент в фоне?
- →Какие поля manifest нужны, чтобы браузер предложил установку?
SeniorТеорияРедкоСравните polling, long-polling, SSE и WebSocket для обновлений в реальном времени.
Сравните polling, long-polling, SSE и WebSocket для обновлений в реальном времени.
Короткий polling периодически делает fetch по таймеру — просто, но расточительно и с задержкой. Long-polling держит каждый запрос открытым до появления данных, затем переподключается — меньше пустых запросов, но всё ещё одно соединение на сообщение. SSE держит один HTTP-поток для push сервер→клиент текстом с автопереподключением — идеален для лент. WebSocket переходит в постоянный полнодуплексный канал для двусторонних бинарных/текстовых данных с низкой задержкой — лучший для чата и игр, но сложнее.
Типичные ошибки
- ✗Путать long-polling с постоянным сокетом — он всё равно переподключается на сообщение
- ✗Брать WebSocket для односторонних лент, где SSE проще и сам переподключается
- ✗Полагать, что у всех четырёх равны задержка и расход трафика
Уточняющие вопросы
- →Почему long-polling снижает пустые ответы, но не стоимость соединения на сообщение?
- →Почему рукопожатие WebSocket начинается как HTTP-запрос upgrade?