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

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

1.8 Middle🔥 291 комментариев
#JavaScript Core#Браузер и сетевые технологии

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

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

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

Разница между then() и async/await

then() и async/await — это два способа работы с промисами в JavaScript. Оба решают проблему асинхронного кода, но имеют принципиальные различия в синтаксисе и подходе.

Основные различия

1. Синтаксис и читаемость

then() - цепочка вызовов (callback style):

function getUserData(userId) {
  return fetch(`/api/users/${userId}`)
    .then(response => response.json())
    .then(user => fetch(`/api/posts/${user.id}`))
    .then(response => response.json())
    .then(posts => ({ user: posts }))
    .catch(error => console.error('Error:', error));
}

async/await - синхронный стиль:

async function getUserData(userId) {
  try {
    const userResponse = await fetch(`/api/users/${userId}`);
    const user = await userResponse.json();
    
    const postsResponse = await fetch(`/api/posts/${user.id}`);
    const posts = await postsResponse.json();
    
    return { user, posts };
  } catch (error) {
    console.error('Error:', error);
  }
}

async/await читается как обычный синхронный код, что делает его более понятным для большинства разработчиков.

2. Обработка ошибок

then() - через catch:

fetch('/api/data')
  .then(res => res.json())
  .then(data => console.log(data))
  .catch(error => {
    console.error('Ошибка:', error);
    // Все ошибки ловятся одним catch
  });

async/await - через try/catch:

async function loadData() {
  try {
    const res = await fetch('/api/data');
    const data = await res.json();
    console.log(data);
  } catch (error) {
    console.error('Ошибка:', error);
    // Более знаком разработчикам
  } finally {
    // Опциональный блок для очистки
  }
}

3. Параллельное выполнение

then() - через Promise.all:

Promise.all([
  fetch('/api/users'),
  fetch('/api/posts'),
  fetch('/api/comments')
])
  .then(responses => Promise.all(responses.map(r => r.json())))
  .then(data => {
    const [users, posts, comments] = data;
    console.log(users, posts, comments);
  });

async/await - более явный:

async function loadAllData() {
  const [usersRes, postsRes, commentsRes] = await Promise.all([
    fetch('/api/users'),
    fetch('/api/posts'),
    fetch('/api/comments')
  ]);
  
  const [users, posts, comments] = await Promise.all([
    usersRes.json(),
    postsRes.json(),
    commentsRes.json()
  ]);
  
  console.log(users, posts, comments);
}

4. Контроль потока выполнения

then() - неявный контроль:

fetch('/api/user')
  .then(res => res.json())
  .then(user => {
    // Вторая операция ждет первую
    return fetch(`/api/posts/${user.id}`);
  })
  .then(res => res.json())
  .then(posts => processData(posts));

async/await - явный контроль:

async function processUserData() {
  const userRes = await fetch('/api/user');
  const user = await userRes.json();
  
  // Явно видно, что это ждет результат выше
  const postsRes = await fetch(`/api/posts/${user.id}`);
  const posts = await postsRes.json();
  
  return processData(posts);
}

Практические рекомендации

Когда выбираю async/await:

  • Читаемость кода важнее
  • Нужна последовательная логика с зависимостями
  • Код содержит условия и циклы в асинхронном потоке
  • Работаю с попыткой/ошибкой (try/catch)
async function getUserWithValidation(userId) {
  try {
    const user = await fetchUser(userId);
    
    if (!user) {
      throw new Error('User not found');
    }
    
    // Цикл в асинхронном коде - очень удобно
    const posts = [];
    for (const postId of user.postIds) {
      posts.push(await fetchPost(postId));
    }
    
    return { user, posts };
  } catch (error) {
    console.error('Failed to load user:', error);
  }
}

Когда выбираю then():

  • Работаю с простыми цепочками операций
  • Нужно использовать функциональный стиль
  • Работаю с методами Promise (Promise.all, Promise.race)
const results = Promise.all(promises)
  .then(data => data.filter(item => item.active))
  .then(filtered => filtered.map(item => item.name));

Смешивание подходов

// Можно комбинировать async/await с then()
async function mixedApproach() {
  const data = await fetch('/api/data')
    .then(res => res.json())
    .then(json => json.filter(item => item.valid));
  
  return data;
}

Важные различия при работе с ошибками

then() не прерывает цепь:

Promise.reject('Error')
  .then(() => 'Step 1')  // Пропускается
  .then(() => 'Step 2')  // Пропускается
  .catch(err => 'Caught'); // Ловится здесь

async/await прерывает выполнение:

async function test() {
  try {
    throw new Error('Error');
    console.log('Never reached');  // Не выполнится
  } catch (err) {
    console.log('Caught');  // Выполнится
  }
}

В современной разработке я предпочитаю async/await за его простоту и читаемость, но хорошо знаю both, так как встречаю legacy код с then() и иногда применяю функциональный style с Promise методами.

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