Пару дней назад я вновь посетил замечательный онлайн-опрос Состояние JS в 2022 году, который собирает данные от разработчиков со всего мира, чтобы увидеть самые последние и будущие тенденции в сообществе JavaScript. Среди данных, которые он собирает, есть раздел, посвященный собственным функциям JavaScript, перечисленным по их использованию и осведомленности. Как вы можете себе представить, среди наиболее часто используемых функций такие популярные, как Необязательное связывание, Нулевое объединение, Веб-сокеты и так далее.

Однако меня не интересовали наиболее используемые или известные API. Вместо этого я искал наименее известные. Я хотел знать, о каких API мы мало говорим, и среди них я нашел четыре чрезвычайно полезных API:

В этой статье мы увидим, что это такое, где их следует использовать и как их использовать.

Примечание: Все эти API доступны в этой демонстрации.

API видимости страницы

Это малоизвестный веб-API, который занимает последнее четвертое место по известности в опросе. Он позволяет узнать, когда пользователь покинул страницу. Точнее, API запускает событие всякий раз, когда изменяется статус видимости страницы: когда пользователь сворачивает или разворачивает окно или переключает вкладку.

Раньше вам приходилось использовать уловки, чтобы узнать, переключил ли пользователь вкладки или свернул окно. Наиболее популярным было использование событий браузера blur и focus.

Использование этих событий приведет к чему-то вроде следующего:

window.addEventListener("focus", function () {
    // User is back on the page
    // Do Something
});


window.addEventListener("blur", function () {
    // User left the page
    // Do Something
});

Предыдущий код работает, но не так, как предполагалось. Поскольку событие blur запускается, когда страница теряет фокус, оно может быть вызвано, когда пользователь щелкает панель поиска, диалоговое окно предупреждения, консоль или границу окна. Таким образом, blur и focus сообщают нам только о том, активна ли страница, но не о том, скрыто или видимо ее содержимое.

СЛУЧАИ ИСПОЛЬЗОВАНИЯ

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

  • приостанавливать видео, карусели изображений или анимацию, когда пользователь покидает страницу;
  • если на странице отображаются текущие данные из API, временно прекратите это поведение, пока пользователя нет;
  • для отправки пользовательской аналитики.

КАК ЭТО ИСПОЛЬЗОВАТЬ?

API видимости страницы предоставляет два свойства и событие для доступа к статусу видимости страницы:

  • document.hiddenОн доступен по всему миру и доступен только для чтения. Старайтесь избегать этого, поскольку сейчас он устарел, но при доступе он возвращает true, если страница скрыта, и false, если она видна.
  • document.visibilityState
    Это обновленная версия document.hidden, но при доступе она возвращает четыре возможных значения в зависимости от статуса видимости страницы:
    - visible Страница видна, а точнее, не свернута. ни в другой вкладке.
    - hiddenСтраница не видна; она свернута или находится в другой вкладке.
    - prerenderЭто исходное состояние видимой страницы во время предварительной отрисовки. Статус видимости страницы может начинаться с prerender, а затем переходить в другое состояние, но не может перейти из другого состояния в prerender.
    - unloadedСтраница выгружается из памяти.
  • visibilitychange
    Это событие, предоставляемое объектом document, которое срабатывает при изменении страницы visibilityState.
document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === "visible") {
        // page is visible
    } else {
        // page is hidden
    }
});

Чтобы увидеть, как использовать API видимости страницы, давайте воспользуемся им, чтобы приостановить видео и прекратить получение ресурсов из API, когда пользователь покидает страницу. Для начала я буду использовать vite.js — замечательный инструмент для быстрого запуска нового проекта:

npm create vite@latest unknown-web-apis

Когда вас попросят выбрать фреймворк, выберите vanilla, чтобы создать стандартный проект JavaScript. После завершения перейдите в новую папку, установите необходимые npm пакетов и запустите сервер разработчика:

cd unknown-web-apis
  npm install
  npm run dev

Перейдите по адресу localhost:3000/, и вы увидите, что ваш проект Vite работает!

Перейдите к файлу /main.js и удалите весь шаблон. Там мы откроем /index.html и внутри тега div #app добавим элемент видео с любым видеофайлом, который вам нужен. Я использовал танцующего Йоши. :)

<div id="app">
    <video controls id="video">
        <source src="./yoshi.mp4" />
    </video>
</div>

Возвращаясь к /main.js, мы добавим прослушиватель событий к объекту document, прослушивающему событие visibilitychange. Там мы можем получить доступ к свойству document.visibilityState, чтобы узнать, видна или скрыта страница.

document.addEventListener("visibilitychange", () => {
    console.log(document.visibilityState);
});

Вы можете перейти в консоль страницы и увидеть изменение статуса видимости страницы при сворачивании окна или переключении на другую вкладку.

Внутри прослушивателя событий мы можем проверить свойство document.visibilityState, приостановить видео, когда оно будет hidden, и воспроизвести его, когда visible. (Разумеется, сначала мы выбираем элемент video, используя document.querySelector().)

const video = document.querySelector("#video");

document.addEventListener("visibilitychange", () => {
    if (document.visibilityState === "visible") {
        video.play();
    } else {
        video.pause();
    }
});

Теперь видео останавливается всякий раз, когда пользователь покидает страницу!

Другое использование API видимости страниц — прекращение получения ненужных ресурсов, когда пользователь не видит страницу. Чтобы убедиться в этом, мы напишем функцию, которая будет постоянно получать случайную цитату из API quotable.io и приостанавливать это поведение, когда страница скрыта.

Мы создадим новый тег div для хранения цитаты в /index.html.

<div id="app">
    <video controls id="video">
        <source src="./yoshi.mp4" />
    </video>
    <div id="quote"></div>
</div>

Вернувшись в /main.js, мы будем использовать Fetch API, чтобы выполнить вызов конечной точки quotable.io https://api.quotable.io/random, а затем вставить его в div quote.

const quote = document.querySelector("#quote");

const getQuote = async () => {
  try {
    const response = await fetch("https://api.quotable.io/random");
    const {content, author, dateAdded} = await response.json();
    const parsedQuote = ` <q>${content}</q> <br> <p>- ${author}</p><br> <p>Added on ${dateAdded}</p>`;
    quote.innerHTML = parsedQuote;
  } catch (error) {
    console.error(error);
  }
};

getQuote();

Давайте кратко объясним, что здесь происходит.

  1. Мы выбираем элемент quote из DOM.
  2. Объявите функцию getQuote, которая представляет собой функцию async, которая позволяет нам использовать ключевое слово await для ожидания, пока мы не получим данные из API.
  3. Полученные данные имеют формат JSON, поэтому мы используем ключевое слово await еще раз, чтобы дождаться, пока данные будут проанализированы в объект JavaScript.
  4. API quotable.io предоставляет нам, помимо прочего, свойства content, author и dateAdded, которые мы внедрим и отобразим в элементе div quote.

Это работает, но цитата извлекается только один раз, поэтому мы можем использовать setInterval() для вызова функции каждые 10 секунд.

const quote = document.querySelector("#quote");

const getQuote = async () => {
  try {
    const response = await fetch("https://api.quotable.io/random");
    const {content, author, dateAdded} = await response.json();
    const parsedQuote = ` <q>${content}</q> <br> <p>- ${author}</p><br> <p>Added on ${dateAdded}</p>`;
    quote.innerHTML = parsedQuote;
  } catch (error) {
    console.error(error);
  }
};

getQuote();
setInterval(getQuote, 10000);

Если пользователь сворачивает окно или переключает вкладку, страница все равно будет получать котировки, создавая ненужную нагрузку на сеть. Чтобы решить эту проблему, мы можем проверить, видна ли страница, прежде чем получать предложение.

const getQuote = async () => {
    if (document.visibilityState === "visible") {
        try {
            const response = await fetch("https://api.quotable.io/random");
            const {content, author, dateAdded} = await response.json();
            const parsedQuote = `
            <q>${content}</q> <br> 
            <p>- ${author}</p><br> 
            <p>Added on ${dateAdded}</p>`;
            quote.innerHTML = parsedQuote;
        } catch (error) {
            console.error(error);
        }
    }
};

getQuote();
setInterval(getQuote, 10000);

Теперь мы будем получать цитату только в том случае, если страница видна пользователю.

ПОДДЕРЖИВАТЬ

Широкая поддержка

API веб-ресурса

ЧТО ЭТО ТАКОЕ?

Web Share API выделяется своей чрезвычайной полезностью среди наименее известных API. Он позволяет вам получить доступ к встроенному в операционную систему механизму общего доступа, что особенно полезно для мобильных пользователей. Таким образом, устраняется необходимость создавать собственные механизмы совместного использования или использовать сторонние.

СЛУЧАИ ИСПОЛЬЗОВАНИЯ

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

КАК ЭТО ИСПОЛЬЗОВАТЬ?

API Web Share предоставляет нам два интерфейса для доступа к системе общего доступа пользователя:

  1. navigator.canShare()Принимает данные, которыми вы хотите поделиться, в качестве аргумента и возвращает логический аргумент в зависимости от того, доступны ли они для совместного использования.
  2. navigator.share()Возвращает обещание, которое будет выполнено в случае успешного обмена. Он вызывает собственный механизм совместного использования и принимает данные, которыми вы хотите поделиться, в качестве аргумента. Обратите внимание, что его можно вызвать только в том случае, если пользователь нажал ссылку или кнопку, т.е. требуется временная активация. Общие данные — это объект, который может иметь следующие свойства:
  • url: URL-адрес для общего доступа,
  • text: текст, которым нужно поделиться,
  • title: заголовок, которым нужно поделиться,
  • files: массив объектов File, представляющих файлы для совместного использования.

Чтобы увидеть, как использовать этот API, мы переработаем наш предыдущий пример и добавим возможность делиться нашими котировками с помощью Web Sharing API. Для начала нам нужно создать кнопку «Поделиться» в /index.html:

<div id="app">
    <video controls id="video">
        <source src="./yoshi.mp4" />
    </video>
    <div id="quote"></div>
    <button type="button" id="share-button">Share Quote</button>
</div>

Направляемся на /main.js и выбираем кнопку «Поделиться» в DOM. Затем мы создаем функцию async для обмена нужными нам данными.

const shareButton = document.querySelector("#share-button");

const shareQuote = async (shareData) => {
    try {
        await navigator.share(shareData);
    } catch (error) {
        console.error(error);
    }
};

Мы можем добавить прослушиватель событий щелчка к элементу shareButton для обратного вызова функции shareQuote. Наше значение shareData.text будет свойством quote.textContent, а shareData.url будет URL-адресом страницы, т. е. свойством location.href.

const shareButton = document.querySelector("#share-button");

const shareQuote = async (shareData) => {
  try {
      await navigator.share(shareData);
  } catch (error) {
      console.error(error);
  }
};

shareButton.addEventListener("click", () => {
  let shareData = {
      title: "A Beautiful Quote",
      text: quote.textContent,
      url: location.href,
  };
 
  shareQuote(shareData);
});

Теперь вы можете поделиться своими цитатами с кем угодно через родную операционную систему. Однако важно отметить, что API веб-ресурса будет работать только в том случае, если контекст защищен, т. е. если страница обслуживается по URL-адресам https:// или wss://.

ПОДДЕРЖИВАТЬ

Плохо поддерживается

API широковещательного канала

ЧТО ЭТО ТАКОЕ?

Еще один API, о котором я хочу поговорить, — это API широковещательного канала. Это позволяет контекстам просмотра отправлять и получать основные данные друг от друга. Контексты просмотра — это такие элементы, как вкладка, окно, iframe или любое другое место, где может отображаться страница. По соображениям безопасности связь между контекстами просмотра не допускается, если они не имеют одного и того же происхождения и не используют API широковещательного канала. Чтобы два контекста просмотра имели одно и то же происхождение, они должны использовать в своем URL-адресе один и тот же протокол (http/https), домен (example.com) и порт (:8080).

СЛУЧАИ ИСПОЛЬЗОВАНИЯ

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

  • Вход или выход пользователя на всех вкладках.
  • Определите, когда ресурс загружается, и покажите его на всех страницах.
  • Поручите сервисному работнику выполнить некоторую фоновую работу.

КАК ЭТО ИСПОЛЬЗОВАТЬ?

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

const broadcast = new BroadcastChannel("new_channel");

Как только мы создадим объект BroadcastChannel с одним и тем же идентификатором в двух контекстах, у него будет два доступных метода для начала взаимодействия:

  • BroadcastChannel.postMessage() для отправки сообщения во все подключенные контексты. В качестве единственного аргумента он принимает объект любого типа, поэтому вы можете отправлять самые разнообразные данные.
broadcast.postMessage("Example message");
  • BroadcastChannel.close(), чтобы закрыть канал и указать браузеру, что он больше не будет получать сообщения и может отправить их в мусор.

Чтобы получить сообщение, у BroadcastChannel есть событие message, которое мы можем прослушать, используя addEventListener или его свойство onmessage. Событие message имеет свойство data с отправленными данными и другие свойства для идентификации контекста, отправившего сообщение, например origin, lastEventId, source и ports.

broadcast.onmessage = ({data, origin}) => {
    console.log(`${origin} says ${data}`);
};

Давайте посмотрим, как использовать API широковещательного канала, на примере нашего предыдущего примера. Нашей целью было бы создать еще один контекст просмотра с тем же источником и отображать одну и ту же цитату в обоих контекстах. Для этого мы создадим новую папку с именем new-origin с новыми файлами /index.html и /main.js внутри.

/new-origin/index.html будет новым шаблоном HTML с элементом div #quote внутри:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <link rel="icon" type="image/svg+xml" href="../favicon.svg" />
        <meta name="viewport" content="width=device-width, initial-scale=1.0" />
        <title>Vite App</title>
    </head>
    <body>
        <div id="quote"></div>
        <script type="module" src="./main.js"></script>
    </body>
</html>

В файле /new-origin/main.js создадим новый канал вещания и выберем элемент #quote из DOM:

const broadcast = new BroadcastChannel("quote_channel");
const quote = document.querySelector("#quote");

А в нашем предыдущем файле /main.js мы создадим новый объект BroadcastChannel и подключим его к "quote_channel". Мы также изменим функцию getQuote, чтобы она отправляла цитату как сообщение в другие контексты.

const broadcast = new BroadcastChannel("quote_channel");

//...

const getQuote = async () => {
  try {
    const response = await fetch("https://api.quotable.io/random");
    const {content, author, dateAdded} = await response.json();
    const parsedQuote = ` <q>${content}</q> <br> <p>- ${author}</p><br> <p>Added on ${dateAdded}</p>`;
    quote.innerHTML = parsedQuote;
    broadcast.postMessage(parsedQuote);
  } catch (error) {
    console.error(error);
  }
};

Вернувшись в файл /new-origin/main.js, мы будем слушать событие message и менять quote.innerHTML каждый раз, когда отправляется новая котировка.

const broadcast = new BroadcastChannel("quote_channel");
const quote = document.querySelector("#quote");

broadcast.onmessage = ({data}) => {
    quote.innerHTML = data;
};

Вы можете увидеть, как кавычка в http://localhost:3000/new-origin/ меняется на кавычку в http://localhost:3000. Также обратите внимание, что цитата не меняется, когда вкладка http://localhost:3000 скрыта, поскольку цитата извлекается только тогда, когда виден статус видимости ее страницы.

ПОДДЕРЖИВАТЬ

Широкая поддержка

API интернационализации

ЧТО ЭТО ТАКОЕ?

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

Допустим, вы хотите отобразить дату «8 ноября 2023 г.» на своей веб-странице, например «8.11.23». Эти данные можно прочитать тремя различными способами в зависимости от страны считывателя:

  • «8 ноября 2023 г.» или ММ/ДД/ГГ людьми из США.
  • «11 августа 2023 г.» или ДД/ММ/ГГ людьми из Европы и Латинской Америки.
  • «23 августа 2011 г.» или ГГ/ММ/ДД, авторы из Японии, Китая и Канады.

Именно здесь на помощь приходит API интернационализации (или i18n API) для решения проблем форматирования в разных языках и регионах. I18n API — замечательный инструмент, который имеет несколько применений, но мы не будем в них углубляться, чтобы не усложнять эту статью.

КАК ЭТО ИСПОЛЬЗОВАТЬ?

API I18n использует для работы идентификаторы локали. Идентификатор локали — это строка, которая выражает язык, страну, регион, диалект и другие предпочтения пользователя. Точнее, идентификатор локали — это строка, состоящая из вложенных тегов, разделенных дефисами. Вложенные теги представляют предпочтения пользователя, такие как язык, страна, регион или алфавит, и форматируются следующим образом:

  1. «ж»: китайский (язык);
  2. «ж-хант»: китайский (язык), написанный традиционными иероглифами (скрипт);
  3. «zh-Hant-TW»: китайский (язык), написанный традиционными иероглифами (скриптом), используемыми в Тайване (регион).

Существует больше вложенных тегов для удовлетворения предпочтений большего количества пользователей (если вы хотите узнать больше, вы можете проверить Определение RFC языковых тегов), но, чтобы быть кратким, API i18n использует эти идентификаторы локали, чтобы знать, как форматировать все данные, чувствительные к языку.

Он предоставляет объект Intl, который предоставляет набор специализированных конструкторов для работы с данными, зависящими от языка. По моему мнению, некоторые из наиболее полезных конструкторов Intl для интернационализации:

  • Intl.DateTimeFormat()Используется для форматирования даты и времени.
  • Intl.DisplayNames()Используется для форматирования отображаемых названий языка, региона и алфавита.
  • Intl.Locale()Используется для создания тегов идентификатора локали и управления ими.
  • Intl.NumberFormat()Используется для форматирования чисел.
  • Intl.RelativeTimeFormat()Используется для форматирования описаний относительного времени.

В нашем примере мы сосредоточимся на конструкторе Intl.DateTimeFormat() для форматирования свойства dateAdded цитаты в зависимости от языкового стандарта пользователя. Конструктор Intl.DateTimeFormat() принимает два аргумента: строку locale, которая определяет соглашение о форматировании даты, и объекты options, позволяющие настроить форматирование дат.

Экземпляр Intl.DateTimeFormat() имеет метод format(), который принимает два аргумента: объект Date, который мы хотим отформатировать, и объект options, позволяющий настроить способ отображения отформатированной даты.

const logDate = (locale) => {
    const newDate = new Date("2022-10-24"); // YYYY-MM-DD
    const dateTime = new Intl.DateTimeFormat(locale, {timeZone: "UTC"});
    const formatedDate = dateTime.format(newDate);
    console.log(formatedDate);
};

logDate("en-US"); // 8/24/2023
logDate("de-DE"); // 24.8.2023
logDate("zh-TW"); // 2023/8/24

Примечание. В аргументеoptionsконструктораIntl.DateTimeFormatмы устанавливаем для свойстваtimeZoneзначение "UTC", поэтому дата не форматируется по местному времени пользователя.

Как вы можете видеть, dateTime.format() меняет дату в зависимости от соглашения о форматировании даты в локали. Мы можем реализовать это поведение для даты кавычек, используя глобальное свойство navigator.language, которое содержит предпочтительный языковой стандарт пользователя. Для этого мы создадим новую функцию, которая принимает строку даты (в формате ГГГГ-ММ-ДД) и возвращает дату, отформатированную в зависимости от локали пользователя.

const formatDate = (dateString) => {
    const date = new Date(dateString);
    const locale = navigator.language;
    const dateTimeFormat = new Intl.DateTimeFormat(locale, {timeZone: "UTC"});
    return dateTimeFormat.format(date);
};

Мы можем добавить эту функцию к функции getQuote() для анализа даты dateAdded.

const getQuote = async () => {
    if (document.visibilityState === "visible") {
        try {
            const response = await fetch("https://api.quotable.io/random");
            const {content, author, dateAdded} = await response.json();

            const parsedQuote = `
            <q>${content}</q> <br> 
            <p>- ${author}</p><br> 
            <p>Added on ${formatDate(dateAdded)}</p>`;

            quote.innerHTML = parsedQuote;
            broadcast.postMessage(parsedQuote);
        } catch (error) {
            console.error(error);
        }
    }
};

При этом наши цитаты локализуются на предпочитаемый пользователем язык! В моем случае мое значение navigator.language равно "en", поэтому мои даты отформатированы в формате ММ/ДД/ГГ.

ПОДДЕРЖИВАТЬ

Широкая поддержка

Заключение

Прочитав эту статью, вы теперь можете узнать о существовании этих API и о том, как их использовать. Несмотря на то, что они заняли последнее место по осведомленности в опросе State of JS Survey, они чрезвычайно полезны, и знание того, как их использовать, определенно улучшит ваш опыт разработки. Тот факт, что эти мощные API не очень известны, означает, что все еще существуют полезные API, о которых вы и я до сих пор не знаем, поэтому сейчас идеальное время, чтобы изучить и найти тот API, который упростит ваш код и сэкономит вам массу времени. время развивается.

Надеюсь, вам понравилась эта статья и до следующих встреч!