Marko — это высокопроизводительный JavaScript-фреймворк, ориентированный на рендеринг компонентов как на стороне сервера, так и на клиенте. Одной из ключевых возможностей при построении интерактивных приложений является работа с асинхронными операциями и событиями. Рассмотрение этих механизмов важно для понимания, как эффективно управлять состоянием компонентов и взаимодействием с внешними источниками данных.
Marko поддерживает асинхронный рендеринг через промисы и
async/await. Это позволяет загружать данные перед
рендерингом компонента, не блокируя основной поток.
// example.marko
<async-component data=asyncData/>
// async-component.marko.js
import { component } from "@marko/runtime";
export default component({
async onCreate(input) {
this.state.data = await fetchData(input.id);
}
});
Ключевые моменты:
onCreate может быть асинхронной функцией. Рендеринг
компонента будет ждать завершения всех асинхронных операций.<div>
$ if(state.data) {
<p>${state.data.name}</p>
} else {
<p>Загрузка...</p>
}
</div>
События в Marko реализуются через механизм on и
emit, который позволяет компонентам взаимодействовать без
прямой зависимости друг от друга. События могут быть синхронными и
асинхронными.
<button on-click("handleClick")>Нажать</button>
export default {
handleClick(event) {
console.log("Кнопка нажата", event);
}
};
Особенности:
on-click связывает DOM-событие с методом
компонента.async handleClick(event) {
const data = await fetchData();
this.state.data = data;
}
Marko позволяет создавать события, которые компоненты могут эмитить и слушать.
<child-component on-update="handleUpdate"/>
// child-component.marko.js
this.emit("update", { value: 42 });
// parent component
handleUpdate(event) {
this.state.value = event.value;
}
Особенности:
emit можно использовать для передачи данных
родителю.Для сложных сценариев с асинхронными зависимостями используется
watch или вычисляемые свойства с поддержкой промисов.
export default {
onCreate() {
this.state.result = null;
this.watch("input", async (newVal) => {
const response = await fetchData(newVal);
this.setState({ result: response });
});
}
};
Ключевые моменты:
watch отслеживает изменения состояния и выполняет
асинхронные операции при изменении данных.Marko поддерживает рендеринг через потоки, что особенно полезно при работе с большими наборами данных или серверным рендерингом с постепенной загрузкой контента.
import { renderToNodeStream } from "@marko/stream";
const stream = renderToNodeStream(template, input);
stream.pipe(res);
Особенности потокового рендеринга:
При работе с асинхронными функциями важно обрабатывать исключения, чтобы не нарушать рендеринг приложения.
async handleClick() {
try {
const data = await fetchData();
this.state.data = data;
} catch (err) {
console.error("Ошибка загрузки данных", err);
this.state.error = true;
}
}
Marko легко интегрируется с любыми промис-базированными библиотеками,
например axios для HTTP-запросов или socket.io
для веб-сокетов.
import axios from "axios";
export default {
async onCreate() {
const response = await axios.get("/api/data");
this.state.data = response.data;
}
};
Асинхронные операции и событийная модель в Marko создают мощный инструмент для построения сложных веб-приложений. Понимание этих механизмов позволяет эффективно управлять состоянием компонентов, минимизировать задержки рендеринга и создавать интерактивные интерфейсы с динамическим контентом.