← Назад к вопросам

В чем разница между async/await и finally?

1.8 Middle🔥 241 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

В чем разница между async/await и finally

Введение

async/await и finally — это разные концепции в JavaScript:

  • async/await — синтаксис для работы с промисами (асинхронным кодом)
  • finally — блок в try/catch, который выполняется всегда

Они решают разные задачи, но часто используются вместе.

1. async/await — синтаксис для асинхронного кода

async — ключевое слово, которое превращает функцию в асинхронную и позволяет использовать await:

// Без async/await (Promises)
function fetchUser() {
  return fetch('/api/user')
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error));
}

// С async/await
async function fetchUser() {
  try {
    const response = await fetch('/api/user');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error(error);
  }
}

await — ключевое слово, которое ждет выполнения промиса:

async function processData() {
  // await ждет, пока промис разрешится
  const user = await fetch('/api/user').then(r => r.json());
  const posts = await fetch(`/api/user/${user.id}/posts`).then(r => r.json());
  return { user, posts };
}

2. finally — блок, который выполняется всегда

finally — часть конструкции try/catch/finally, которая выполняется независимо от результата:

// Без finally
try {
  const data = JSON.parse(jsonString);
  console.log(data);
} catch (error) {
  console.error('Parse error:', error);
}
console.log('Done'); // Выполнится всегда

// С finally
try {
  const data = JSON.parse(jsonString);
  console.log(data);
} catch (error) {
  console.error('Parse error:', error);
} finally {
  console.log('Done'); // Гарантированно выполнится
}

3. Разница: структура и назначение

Аспектasync/awaitfinally
ТипСинтаксис для асинхронного кодаБлок обработки исключений
НазначениеУпрощение работы с промисамиОчистка ресурсов
ИспользованиеВ функцияхВ try/catch
ВыполнениеПоследовательноеВсегда (успех или ошибка)
АналогPromises с .then/.catchfinally для синхронного кода

4. async/await: примеры

// Простой пример
async function greet() {
  return 'Hello';
}

const result = greet(); // Возвращает Promise
await greet(); // 'Hello'

// Множественные await
async function getUserData(userId) {
  const user = await fetch(`/api/users/${userId}`).then(r => r.json());
  const comments = await fetch(`/api/users/${userId}/comments`).then(r => r.json());
  const posts = await fetch(`/api/users/${userId}/posts`).then(r => r.json());
  return { user, comments, posts };
}

// Параллельное выполнение
async function getMultipleUsers(ids) {
  const users = await Promise.all(
    ids.map(id => fetch(`/api/users/${id}`).then(r => r.json()))
  );
  return users;
}

5. finally: примеры

// finally в синхронном коде
try {
  const data = JSON.parse(jsonString);
} catch (error) {
  console.error('Error:', error);
} finally {
  console.log('Parsing attempt finished');
}

// finally в асинхронном коде
async function fetchData() {
  let data;
  try {
    data = await fetch('/api/data').then(r => r.json());
  } catch (error) {
    console.error('Fetch failed:', error);
  } finally {
    console.log('Fetch attempt finished');
  }
  return data;
}

6. Использование вместе: try/catch/finally с async/await

async function processFile(filename) {
  let file;
  try {
    // 1. Загружаем файл (async)
    const response = await fetch(`/files/${filename}`);
    if (!response.ok) throw new Error('File not found');
    file = await response.json();
    console.log('File loaded:', file);
  } catch (error) {
    // 2. Обработка ошибок
    console.error('Error:', error.message);
  } finally {
    // 3. Очистка (выполнится всегда)
    console.log('Processing finished');
  }
}

7. Практический пример: управление ресурсами

// Пример с finally для очистки ресурсов
async function fetchUserData(userId) {
  let connection;
  
  try {
    // Создаем соединение
    connection = await openDatabase();
    
    // Запрашиваем данные
    const user = await connection.query('SELECT * FROM users WHERE id = ?', [userId]);
    console.log('User data:', user);
    
    return user;
  } catch (error) {
    console.error('Database error:', error);
    throw error; // Пробрасываем ошибку дальше
  } finally {
    // Очищаем соединение (выполнится даже при ошибке)
    if (connection) {
      await connection.close();
      console.log('Connection closed');
    }
  }
}

8. finally гарантирует выполнение кода

Это особенно важно для очистки ресурсов:

async function downloadFile() {
  const startTime = Date.now();
  
  try {
    // Загружаем файл
    const file = await fetch('/file.zip').then(r => r.blob());
    saveFile(file);
    console.log('File saved');
    return file;
  } catch (error) {
    console.error('Download failed:', error);
    throw error;
  } finally {
    // Логируем время выполнения (выполнится всегда)
    const elapsed = Date.now() - startTime;
    console.log(`Operation took ${elapsed}ms`);
    
    // Закрываем UI элементы (прогресс бар и т.д.)
    closeProgressBar();
  }
}

// Результат:
// 1. Попытка загрузить файл
// 2. При успехе: "File saved" + "Operation took XXXms"
// 3. При ошибке: "Download failed" + "Operation took XXXms"
// 4. finally всегда выполнится и закроет прогресс бар

9. Сравнение: Promises vs async/await

// С Promises и .finally()
fetch('/api/data')
  .then(r => r.json())
  .then(data => console.log(data))
  .catch(error => console.error(error))
  .finally(() => console.log('Done'));

// С async/await и finally
async function getData() {
  try {
    const r = await fetch('/api/data');
    const data = await r.json();
    console.log(data);
  } catch (error) {
    console.error(error);
  } finally {
    console.log('Done');
  }
}

// Обе версии имеют одинаковый результат, но async/await более читаемый

10. Частые ошибки

// ❌ Неправильно: finally не заменяет catch
async function badExample() {
  try {
    const data = await fetch('/api/data').then(r => r.json());
    console.log(data);
  } finally {
    // Ошибка будет залогирована, но не обработана
    console.log('Done');
  }
}

// ✅ Правильно: используй catch для обработки ошибок
async function goodExample() {
  try {
    const data = await fetch('/api/data').then(r => r.json());
    console.log(data);
  } catch (error) {
    console.error('Error:', error);
  } finally {
    console.log('Done');
  }
}

// ❌ Неправильно: await вне async функции
function badAsync() {
  await fetch('/api/data'); // SyntaxError
}

// ✅ Правильно: await только в async функциях
async function goodAsync() {
  await fetch('/api/data');
}

Заключение

  • async/await — это синтаксис для упрощенной работы с асинхронным кодом (промисами)
  • finally — это блок, который выполняется всегда, независимо от успеха или ошибки
  • Они решают разные проблемы и часто используются вместе: async/await для асинхронного кода, finally для гарантированной очистки ресурсов
В чем разница между async/await и finally? | PrepBro