В вебе есть множество API для информирования о том, что происходит в вашем приложении. Вы можете мониторить множество вещей и наблюдать практически любые типы изменений.

Эти изменения варьируются от простых вещей типа мутаций DOM и отлова ошибок на клиентской части до более сложных уведомлений типа разрядки батареи устройства пользователя. При этом остается постоянным набор способов взаимодействия с ними: функции обратного вызова, промисы, события.

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

Прослушиваем события DOM (как нативные, так и кастомные)

// user scrolls the page.
window.addEventListener('scroll', e => { ... });

el.addEventListener('focus', e => { ... }); // el is focused. img.addEventListener('load', e => { ... }); // img is done loading.

// user types into input.
input.addEventListener('input', e => { ... });

// catch custom event fired on el.
el.addEventListener('custom-event', e => { ... });

Прослушиваем модификацию DOM

const observer = new MutationObserver(mutations => { ... }); observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
characterData: true
});

Узнаем об изменении URL

window.onhashchange = e => console.log(location.hash); window.onpopstate = e => console.log(document.location, e.state);

Узнаем о работе приложения в полноэкранном режиме (подробнее)

document.addEventListener('fullscreenchange', e => {
console.log(document.fullscreenElement)
});

Узнаем о поступлении сообщений по WebRTC

// Cross-domain / window /worker.
window.onmessage = e => { ... };

// WebRTC
const dc = (new RTCPeerConnection()).createDataChannel(); dc.onmessage = e => { ... };

Узнаем об ошибках на клиентской стороне (подробнее)

// Client-size error?
window.onerror = (msg, src, lineno, colno, error) => { ... };

// Unhandled rejected Promise?
window.onunhandledrejection = e => console.log(e.reason);

Отслеживаем изменение ориентации экрана устройства (подробнее)

const media = window.matchMedia('(orientation: portrait)'); media.addListener(mql => console.log(mql.matches));

// Orientation of device changes.
window.addEventListener('orientationchange', e => {
console.log(screen.orientation.angle)
});

Отслеживаем изменения в сетевом соединении (подробнее)

// Online/offline events.
window.addEventListener('online', e => {
console.assert(navigator.onLine)
});
window.addEventListener('offline', e => {
console.assert(!navigator.onLine)
});

// Network Information API navigator.connection.addEventListener('change', e => {
console.log(navigator.connection.type,
navigator.connection.downlinkMax);
});

Отслеживаем состояние заряда батареи устройства (подробнее)

navigator.getBattery().then(batt => {
batt.addEventListener('chargingchange', e => {
console.log(batt.charging);
});
batt.addEventListener('levelchange',e => {
console.log(batt.level);
});
batt.addEventListener('chargingtimechange', e => {
console.log(batt.chargingTime);
});
batt.addEventListener('dischargingtimechange', e => {
console.log(batt.dischargingTime);
});
});

Узнаем о видимости/нахождении в фокусе вкладки или страницы (подробнее)

document.addEventListener('visibilitychange', e => {
console.log(document.hidden)
});

Узнаем о смене пользователем расположения

navigator.geolocation.watchPosition(pos => console.log(pos.coords));

Узнаем о изменении разрешений на использование нужного API (подробнее)

const q = navigator.permissions.query({name: 'geolocation'}); q.then(permission => {
permission.addEventListener('change', e => {
console.log(e.target.state);
});
});

Узнаем об обновлении другой вкладкой локального хранилища или хранилища сессии

window.addEventListener('storage', e => alert(e));

Узнаем о появлении или покидании элементом области видимости (то есть о видимости элемента, подробнее)

const observer = new IntersectionObserver(changes => {
...
}, {threshold: [0.25]}); observer.observe(document.querySelector('#watchMe'));

Узнаем, когда браузер находится в “ленивом” режиме (и готов выполнить какую-нибудь дополнительную работу, подробнее)

requestIdleCallback(deadline => { ... }, {timeout: 2000});

Узнаем о загрузке браузером ресурса или о записи метрики User Timing (подробнее)

const observer = new PerformanceObserver(list => {
console.log(list.getEntries());
});
observer.observe({entryTypes: ['resource', 'mark', 'measure']});

Узнаем об изменении свойств объекта (включая свойства DOM, подробнее)

// Observe changes to a DOM node's .textContent.
// From gist.github.com/ebidel/d923001dd7244dbd3fe0d5116050d227

const proxy = new Proxy(document.querySelector('#target'), {
set(target, propKey, value, receiver) {
if (propKey === 'textContent') {
console.log('textContent changed to: ' + value);
}
target[propKey] = value;
}
});
proxy.textContent = 'Updated content!';

Круто! И, главное, что еще большее количество API находится в разработке.

Я предполагаю, что вы могли бы классифицировать некоторые из этих примеров как техники и паттерны (например, реагирование на события DOM). Однако многие совершенно новые API создавались с определенной целью: измерение производительности, информирование о заряде батареи, состояния онлайн или офлайн.

Это действительно впечатляет, к каким вещам у веб-разработчиков есть доступ в наши дни. API есть практически для всего.

Источник: http://prgssr.ru/development/monitoring-veb-prilozhenij.html

⤧  Next post Темизация с Sass: бесконечная история ⤧  Previous post Настройка экрана входа lightdm-gtk-greeter