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

В чем разница между Promise и Observable в Angular?

1.6 Junior🔥 71 комментариев
#JavaScript Core

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

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

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

Разница между Promise и Observable в Angular

Promise и Observable — это два способа работы с асинхронными операциями в JavaScript и TypeScript. Angular (особенно версии 2+) широко использует Observable через RxJS, но понимание различий критически важно для правильного проектирования приложений.

Promise — один результат

Promise - это объект, который представляет одно значение, которое может быть доступно сейчас, в будущем или никогда:

// Promise создается с одним значением
const promise = new Promise((resolve, reject) => {
  setTimeout(() => resolve('Done!'), 1000);
});

promise.then(result => console.log(result));

// Результат: 'Done!' (один раз, через 1 секунду)

Характеристики Promise:

  • Выполняется один раз
  • Если уже выполнен, новые подписки получают результат из кэша
  • Нельзя отменить (нет встроенного механизма)
  • Синхронное создание, асинхронное выполнение

Observable — множество результатов

Observable - это поток данных, который может испускать множество значений со временем:

import { Observable, interval } from 'rxjs';

const observable = new Observable(subscriber => {
  subscriber.next('Значение 1');
  subscriber.next('Значение 2');
  subscriber.next('Значение 3');
  subscriber.complete();
});

observable.subscribe(value => console.log(value));

// Результат:
// 'Значение 1'
// 'Значение 2'
// 'Значение 3'

// Пример: интервал
const interval$ = interval(1000); // Испускает число каждую секунду
interval$.subscribe(n => console.log(n)); // 0, 1, 2, 3, ...

Характеристики Observable:

  • Может испускать множество значений
  • Ленивое выполнение (пока нет подписчиков, ничего не происходит)
  • Можно отменить (через unsubscribe)
  • Каждая подписка создает новый поток

Таблица сравнения

                    Promise              Observable
─────────────────────────────────────────────────────
Значения           Одно                 Множество
Время              Один раз             Со временем
Отмена             Нельзя               Можно (unsubscribe)
Ленивость          Нет                  Да (горячие/холодные)
Операции           .then()/.catch()     .pipe(), .subscribe()
Полезность         HTTP запросы         Потоки данных
─────────────────────────────────────────────────────

Promise в Angular

// Пример: HTTP запрос с Promise
function getUserWithPromise(id: string): Promise<User> {
  return fetch(`/api/users/${id}`)
    .then(response => response.json())
    .then(data => data as User);
}

// Использование
getUserWithPromise('123')
  .then(user => console.log(user))
  .catch(error => console.error(error));

Observable в Angular (предпочтительно)

// Пример: HTTP запрос с Observable
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class UserService {
  constructor(private http: HttpClient) {}
  
  getUser(id: string): Observable<User> {
    return this.http.get<User>(`/api/users/${id}`);
  }
}

// Использование в компоненте
@Component({
  template: `<div>{{ (user$ | async)?.name }}</div>`
})
export class UserComponent implements OnInit {
  user$: Observable<User>;
  
  constructor(private userService: UserService) {}
  
  ngOnInit() {
    this.user$ = this.userService.getUser('123');
  }
}

Практические примеры различий

1. Множество значений (Observable)

// Promise - не может обработать
const promise = new Promise((resolve) => {
  resolve(1);
  resolve(2); // Игнорируется!
});
promise.then(v => console.log(v)); // 1

// Observable - может обработать
const observable = new Observable(subscriber => {
  subscriber.next(1);
  subscriber.next(2);
  subscriber.next(3);
});
observable.subscribe(v => console.log(v)); // 1, 2, 3

**2. Отмена операции (Observable)

// Promise - нельзя отменить
const promise = fetch('/api/users/123');
promise.cancel(); // Ошибка! Нет такого метода

// Observable - можно отменить
const subscription = this.http.get('/api/users/123').subscribe();
subscription.unsubscribe(); // Запрос отменяется

**3. Трансформация данных (Observable)

import { map, filter, switchMap } from 'rxjs/operators';

// Promise
fetch('/api/users/123')
  .then(r => r.json())
  .then(user => user.name)
  .then(name => name.toUpperCase())
  .then(uppercaseName => console.log(uppercaseName));

// Observable - более элегантно
this.http.get<User>('/api/users/123')
  .pipe(
    map(user => user.name),
    map(name => name.toUpperCase())
  )
  .subscribe(console.log);

**4. Совместная работа (switchMap)

// Зависимые запросы
const userId$ = of('123');

const userWithPosts$ = userId$.pipe(
  switchMap(id => this.userService.getUser(id)),
  switchMap(user => this.postService.getUserPosts(user.id))
);

userWithPosts$.subscribe(posts => console.log(posts));

Angular HttpClient

Angular HttpClient возвращает Observable, а не Promise:

@Injectable()
export class DataService {
  constructor(private http: HttpClient) {}
  
  // Возвращает Observable
  getData(): Observable<Data> {
    return this.http.get<Data>('/api/data');
  }
  
  // Если нужен Promise, можно конвертировать
  getDataAsPromise(): Promise<Data> {
    return this.http.get<Data>('/api/data').toPromise();
  }
}

Когда использовать

Promise:

  • Простые асинхронные операции
  • Один результат
  • Не нужна отмена
  • Простой callback hell

Observable:

  • Потоки данных
  • Множественные значения
  • Нужна отмена
  • Сложные трансформации
  • WebSocket
  • Angular (везде используется RxJS)

Итог

Angular использует Observable как основной способ работы с асинхронностью. Observable более мощный и гибкий, чем Promise, позволяя работать с потоками данных, трансформировать их через операторы, отменять подписки и комбинировать сложные асинхронные логики в читаемом и декларативном стиле.

В чем разница между Promise и Observable в Angular? | PrepBro