Пошук уроків, статей та іншого контенту
Порівняє синхронну й асинхронну взаємодію, їхні переваги, обмеження та типові сценарії використання.
У системі різні компоненти постійно обмінюються даними:
вебклієнт надсилає запит серверу;
один сервіс запитує дані в іншого;
сервер повідомляє сервісу про нове замовлення;
застосунок записує подію в чергу повідомлень.
Один із важливих способів описати таку взаємодію — визначити, чи повинен відправник чекати на відповідь.
Синхронна комунікація — відправник надсилає запит і чекає на результат.
Асинхронна комунікація — відправник надсилає повідомлення і може продовжити роботу, не чекаючи негайної відповіді.
Під час синхронної взаємодії послідовність зазвичай виглядає так:
Компонент A надсилає запит.
Компонент A очікує.
Компонент B обробляє запит.
Компонент B повертає відповідь.
Компонент A продовжує роботу.
Наприклад, клієнт запитує профіль користувача. Щоб показати сторінку, клієнту потрібна відповідь сервера, тому він очікує на неї.
Клієнт ── запит профілю ──> Сервер
Клієнт <── дані профілю ─── СерверСинхронна комунікація зручна, коли:
результат потрібен одразу;
наступний крок залежить від відповіді;
операція проста для розуміння;
важливо негайно повідомити користувача про успіх або помилку.
Приклади:
перевірка облікових даних під час входу;
отримання даних для відображення сторінки;
перевірка доступності товару перед оформленням замовлення;
збереження форми, коли користувачу потрібно показати результат.
Головний недолік — відправник залежить від доступності та швидкості отримувача.
Якщо сервер:
працює повільно;
тимчасово недоступний;
перевантажений;
очікує відповідь від іншого сервісу,
то клієнт також змушений чекати або отримує помилку.
Синхронний ланцюжок із кількох компонентів може виглядати так:
Клієнт → Сервіс замовлень → Сервіс оплати → Сервіс складуЯкщо кожен сервіс чекає на наступний, загальний час відповіді збільшується. Несправність одного сервісу може вплинути на всю операцію.
Під час асинхронної взаємодії відправник не повинен чекати на негайну відповідь:
Компонент A надсилає повідомлення.
Компонент A продовжує роботу.
Компонент B обробляє повідомлення пізніше.
Результат передається окремим повідомленням або стає доступним згодом.
Сервіс замовлень ── подія "замовлення створено" ──> Черга
Сервіс замовлень продовжує роботу
Сервіс сповіщень читає подію пізніше
Сервіс аналітики читає подію пізнішеВажливо: асинхронність не означає, що операція виконується миттєво. Вона означає, що відправник не блокує свою роботу в очікуванні результату.
Асинхронна комунікація корисна, коли:
результат не потрібен негайно;
операція може тривати довго;
систему потрібно зробити стійкішою до тимчасової недоступності компонентів;
одне повідомлення мають обробити кілька незалежних компонентів;
потрібно уникнути довгого очікування користувача.
Приклади:
надсилання електронного листа після реєстрації;
створення звіту у фоновому режимі;
обробка зображення або відео;
запис подій для аналітики;
надсилання сповіщень;
оновлення пошукового індексу після зміни даних.
Після створення замовлення сервіс може не чекати, доки завершаться всі другорядні дії:
1. Сервіс замовлень створює замовлення.
2. Сервіс замовлень одразу відповідає клієнту.
3. Окремі компоненти пізніше:
- надсилають лист;
- оновлюють аналітику;
- резервують товар;
- створюють сповіщення.Асинхронна взаємодія складніша для проєктування та налагодження.
Потрібно враховувати:
коли саме повідомлення буде оброблено;
що станеться, якщо обробник тимчасово недоступний;
чи можна повторно обробити одне повідомлення;
як відстежувати помилки;
як повідомити користувача про остаточний результат;
чи важливий порядок повідомлень.
Крім того, результат може бути не відомий одразу. Користувачу іноді доводиться показувати статус:
«Обробку розпочато»;
«Очікує виконання»;
«Завершено»;
«Не вдалося виконати».
У JavaScript асинхронну операцію зручно представляти об’єктом Promise. У прикладі нижче затримка імітує звернення до віддаленого сервісу.
function getUserSynchronously() {
console.log("Синхронний запит: очікуємо відповідь");
// Імітація відповіді, яка вже доступна
return { id: 1, name: "Олена" };
}
function getUserAsynchronously() {
return new Promise((resolve) => {
setTimeout(() => {
resolve({ id: 1, name: "Олена" });
}, 1000);
});
}
async function main() {
const user = getUserSynchronously();
console.log(`Синхронно отримано: ${user.name}`);
console.log("Асинхронний запит: продовжуємо іншу роботу");
const userPromise = getUserAsynchronously();
console.log("Іншу роботу виконано");
const asyncUser = await userPromise;
console.log(`Асинхронно отримано: ${asyncUser.name}`);
}
main();Можливий порядок виведення:
Синхронний запит: очікуємо відповідь
Синхронно отримано: Олена
Асинхронний запит: продовжуємо іншу роботу
Іншу роботу виконано
Асинхронно отримано: ОленаУ синхронному прикладі результат повертається безпосередньо, і код використовує його одразу.
В асинхронному прикладі:
запускається операція;
програма виконує іншу роботу;
await очікує результат лише в тому місці, де він справді потрібен;
після завершення операції код продовжується.
Цей приклад лише імітує віддалений сервіс. У реальній системі між компонентами можуть використовуватися HTTP-запити, повідомлення або інші механізми обміну даними.
Синхронна комунікація зазвичай підходить, якщо:
відповідь потрібна для поточної операції;
користувач очікує результат зараз;
операція коротка і передбачувана;
помилку потрібно одразу показати відправнику.
Асинхронна комунікація зазвичай підходить, якщо:
операція довга;
результат можна отримати пізніше;
відправник не повинен залежати від миттєвої доступності отримувача;
повідомлення можуть оброблятися у фоновому режимі;
одна подія має запускати кілька незалежних дій.
У реальних системах часто використовують обидва підходи. Наприклад:
клієнт синхронно надсилає запит на створення замовлення;
сервер синхронно перевіряє основні дані;
сервер повертає ідентифікатор замовлення;
надсилання листа та оновлення аналітики відбуваються асинхронно.
Так користувач швидко отримує відповідь, а другорядні операції не збільшують час очікування.
Запуск асинхронної операції не означає, що результат уже доступний.
const result = getUserAsynchronously();
console.log(result.name); // Помилка: result ще є PromiseПотрібно дочекатися результату:
const result = await getUserAsynchronously();
console.log(result.name);Або обробити Promise за допомогою .then().
Якщо наступний крок не може виконуватися без відповіді, надмірне розділення операції на фонові повідомлення ускладнить систему.
Наприклад, не варто створювати замовлення, якщо критична перевірка оплати ще не виконана і результат цієї перевірки потрібен негайно.
Асинхронна операція може завершитися невдало. Потрібно передбачити, що робити в такому випадку:
повторити операцію;
повідомити користувача;
зберегти помилку для подальшого аналізу;
передати повідомлення на повторну обробку.
Асинхронне повідомлення може бути оброблено із затримкою. Код не повинен покладатися на миттєву зміну даних, якщо система цього не гарантує.
У деяких системах повідомлення може бути доставлене повторно. Обробник має бути готовим до цього, щоб повторна обробка не створила дублікати або некоректний стан.
Синхронна комунікація передбачає очікування відповіді перед продовженням операції.
Вона проста для розуміння та підходить, коли результат потрібен одразу.
Асинхронна комунікація дає змогу продовжити роботу без негайного очікування результату.
Вона корисна для довгих, фонових і незалежних операцій.
Асинхронність потребує продуманого опрацювання затримок, помилок і повторних повідомлень.
У більшості реальних систем синхронні та асинхронні взаємодії використовують разом.