Асинхронные операции в JavaScript — это операции, выполнение которых занимает время и не блокирует основной поток исполнения кода. В контексте Riot.js асинхронность особенно важна при работе с API, загрузке данных с сервера, таймерами или любыми другими задержками. Riot.js предоставляет гибкие механизмы для интеграции асинхронного кода с реактивными компонентами.
async/await внутри компонентовRiot.js позволяет определять методы компонентов, в которых можно
применять синтаксис async/await. Это упрощает работу с
промисами и делает код более читаемым.
<user-list>
<ul>
<li each={user in users}>{user.name}</li>
</ul>
<script>
import { onMounted } from 'riot';
export default {
users: [],
async fetchUsers() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/users');
this.users = await response.json();
} catch (error) {
console.error('Ошибка загрузки пользователей:', error);
}
},
onMounted() {
this.fetchUsers();
}
}
</script>
</user-list>
Ключевые моменты:
fetchUsers объявлен как async, что
позволяет использовать await для промисов.users) автоматически обновляет
отображение при присвоении нового значения.onMounted,
удобно использовать для запуска асинхронных операций после монтирования
компонента.Для обработки промисов можно использовать стандартные методы
then и catch. Этот подход полезен, если не
требуется синтаксис async/await.
<posts-list>
<ul>
<li each={post in posts}>{post.title}</li>
</ul>
<script>
export default {
posts: [],
fetchPosts() {
fetch('https://jsonplaceholder.typicode.com/posts')
.then(res => res.json())
.then(data => this.posts = data)
.catch(err => console.error('Ошибка загрузки постов:', err));
},
onMounted() {
this.fetchPosts();
}
}
</script>
</posts-list>
Особенности подхода с then:
catch.async/await.Riot.js использует реактивное обновление DOM на основе изменений состояния компонентов. Асинхронные операции напрямую взаимодействуют с этим механизмом:
<todo-app>
<ul>
<li each={item INTOdos}>{item.task} - {item.completed ? 'Выполнено' : 'В процессе'}</li>
</ul>
<script>
export default {
todos: [],
async loadTodos() {
const res = await fetch('/api/todos');
this.todos = await res.json();
},
toggleTodoCompletion(todo) {
todo.completed = !todo.completed;
},
onMounted() {
this.loadTodos();
}
}
</script>
</todo-app>
Пояснения:
toggleTodoCompletion мгновенно обновляет
интерфейс без дополнительных вызовов ререндеринга.loadTodos интегрирована с
реактивным массивом todos.Часто требуется выполнять несколько асинхронных задач одновременно и
обрабатывать результаты после завершения всех операций. Для этого
используется Promise.all или
Promise.allSettled.
<dashboard>
<div>
<h3>Данные пользователей</h3>
<pre>{JSON.stringify(users)}</pre>
<h3>Статистика постов</h3>
<pre>{JSON.stringify(posts)}</pre>
</div>
<script>
export default {
users: [],
posts: [],
async loadData() {
try {
const [usersData, postsData] = await Promise.all([
fetch('/api/users').then(res => res.json()),
fetch('/api/posts').then(res => res.json())
]);
this.users = usersData;
this.posts = postsData;
} catch (error) {
console.error('Ошибка загрузки данных:', error);
}
},
onMounted() {
this.loadData();
}
}
</script>
</dashboard>
Особенности использования
Promise.all:
Promise.all отклоняется.Promise.allSettled.Riot.js позволяет асинхронно обрабатывать события пользователя, сохраняя реактивность интерфейса:
<search-bar>
<input onin put={handleInput} placeholder="Поиск..." />
<ul>
<li each={result in results}>{result.name}</li>
</ul>
<script>
export default {
results: [],
async handleInput(event) {
const query = event.target.value;
if (!query) {
this.results = [];
return;
}
try {
const res = await fetch(`/api/search?q=${encodeURIComponent(query)}`);
this.results = await res.json();
} catch (err) {
console.error('Ошибка поиска:', err);
}
}
}
</script>
</search-bar>
results автоматически
отображает новые данные в DOM.this: Внутри асинхронных
функций this сохраняется, если используется синтаксис
методов объекта. При использовании обычных функций или стрелочных
функций нужно следить за контекстом.await или промисы в блоки try/catch, чтобы не
возникали необработанные исключения, которые могут нарушить реактивность
компонента.await в цикле блокирует
поток, тогда как Promise.all ускоряет параллельную загрузку
данных.Асинхронность в Riot.js интегрирована с реактивностью компонентов,
что позволяет создавать динамичные и отзывчивые интерфейсы.
Использование async/await, промисов и методов жизненного
цикла обеспечивает плавное взаимодействие с внешними API и динамическими
данными, сохраняя чистоту и читаемость кода.