Lit — современный фреймворк для создания веб-компонентов, который
делает работу с шаблонами и реактивностью проще и эффективнее. Одной из
мощных возможностей является поддержка асинхронных данных прямо в
шаблонах с использованием Promise и специальных конструкций
фреймворка. Это позволяет создавать интерфейсы, которые динамически
подгружают данные, управляют состояниями загрузки и ошибок, сохраняя
чистоту кода и реактивность компонентов.
async и await в шаблонахВ Lit шаблон определяется через функцию render, которая
возвращает результат работы функции html. Когда данные
получаются асинхронно, например через fetch, их можно
обрабатывать с помощью промисов. Стандартный способ — хранить промис в
свойстве компонента и использовать его внутри шаблона.
import { LitElement, html } from 'lit';
class AsyncExample extends LitElement {
static properties = {
dataPromise: { type: Object }
};
constructor() {
super();
this.dataPromise = fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json());
}
render() {
return html`
${this.dataPromise.then(data => html`
<div>Задача: ${data.title}</div>
`)}
`;
}
}
customElements.define('async-example', AsyncExample);
В этом примере dataPromise хранит промис, который при
разрешении возвращает данные. Внутри шаблона используется метод
then, чтобы получить результат и отрендерить его.
untilLit предоставляет удобную директиву until, которая
позволяет рендерить «заглушку» до того момента, пока промис не
разрешится. Это особенно полезно для отображения состояния загрузки.
import { until } from 'lit/directives/until.js';
render() {
return html`
${until(
this.dataPromise.then(data => html`<div>${data.title}</div>`),
html`<div>Загрузка...</div>`
)}
`;
}
Преимущества until:
Работа с асинхронными данными требует обработки возможных ошибок. В
Lit это можно делать через цепочку catch промиса или внутри
директивы until с fallback-шаблоном.
this.dataPromise = fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => {
if (!response.ok) throw new Error('Ошибка загрузки');
return response.json();
})
.catch(error => ({ error: error.message }));
render() {
return html`
${until(
this.dataPromise.then(data => data.error
? html`<div>Ошибка: ${data.error}</div>`
: html`<div>Задача: ${data.title}</div>`),
html`<div>Загрузка...</div>`
)}
`;
}
Это позволяет безопасно обрабатывать любые сбои сетевых запросов и сохранять стабильность интерфейса.
Иногда необходимо вычислять данные динамически на основе других свойств, возвращая промис. В Lit можно организовать это через геттеры и реактивные свойства.
static properties = {
userId: { type: Number },
userData: { type: Object }
};
updated(changedProperties) {
if (changedProperties.has('userId')) {
this.userData = this.fetchUserData(this.userId);
}
}
async fetchUserData(id) {
const response = await fetch(`https://jsonplaceholder.typicode.com/users/${id}`);
return await response.json();
}
render() {
return html`
${until(
this.userData.then(user => html`<div>Имя: ${user.name}</div>`),
html`<div>Загрузка данных пользователя...</div>`
)}
`;
}
Такой подход позволяет автоматически перерендеривать компонент при изменении ключевого свойства и асинхронно подгружать зависимые данные.
Lit поддерживает объединение нескольких промисов для одновременной
загрузки нескольких ресурсов. Это делается через стандартный
Promise.all.
this.dataPromise = Promise.all([
fetch('/api/posts').then(r => r.json()),
fetch('/api/comments').then(r => r.json())
]);
render() {
return html`
${until(
this.dataPromise.then(([posts, comments]) => html`
<div>Посты: ${posts.length}</div>
<div>Комментарии: ${comments.length}</div>
`),
html`<div>Загрузка данных...</div>`
)}
`;
}
Использование Promise.all в сочетании с
until делает код лаконичным и легко поддерживаемым при
работе с несколькими источниками данных одновременно.
until для асинхронных данных, чтобы
минимизировать мерцание интерфейса.async
функции внутри методов компонента вместо длинных цепочек
then.Асинхронные шаблоны в Lit обеспечивают гибкий и реактивный подход к работе с динамическими данными, позволяя строить современные веб-компоненты с минимальными усилиями и высоким уровнем контроля над состояниями загрузки и ошибок.