Rxjs – использование EMPTY в сочетании с финализацией без запуска

взяв в качестве примера следующий код:

const subject$ = new Subject();

subject$
  .pipe(
    tap(() => console.info('tap1')),
    switchMap(() => EMPTY),
    tap(() => console.info('tap2')),
    finalize(() => console.info('finalize')),
  ).subscribe();

subject$.next(null);

Я пытаюсь достичь следующего результата:

Expected Output:
tap1
finalize

Actual Output:
tap1

Чтение того, что делает каждый оператор, должно работать должным образом, но это не так.

Мой мыслительный процесс был:

  1. у меня есть предмет, который выдает значения
  2. я переключаю наблюдаемую на новую, в данном случае ПУСТОЙ
  3. Поскольку EMPTY согласно документации выдает полное уведомление без выдачи элементов, которые, как я ожидал, tap2 не будут регистрироваться и finalize будут регистрироваться, поскольку связанное наблюдаемое было завершено.

Я явно не понимаю. Может ли кто-нибудь помочь мне понять поток и как заставить его работать для моих нужд, пожалуйста?

Освоение Observables и Subjects в Rxjs:
Освоение Observables и Subjects в Rxjs:
Давайте начнем с основ и постепенно перейдем к более продвинутым концепциям в RxJS в Angular
Promise v/s Observable в Angular
Promise v/s Observable в Angular
В системах Push производитель определяет, когда отправить данные потребителю. Потребитель не знает, когда он получит эти данные.
Подсказка RxJS [filter, skipWhile]
Подсказка RxJS [filter, skipWhile]
Эта подсказка описывает разницу между операторами filter и skipWhile из библиотеки RxJS .
В чем разница между Promise и Observable?
В чем разница между Promise и Observable?
Разберитесь в этом вопросе, и вы значительно повысите уровень своей компетенции.
4
0
59
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Пустое завершает, вы правы, но это завершит поток только тогда, когда EMPTY будет началом потока!

EMPTY.pipe(finalize(() => console.info('finalize'))).subscribe({
  next: () => console.info('Next'),
  complete: () => console.info('Complete!'),
});

// will output
// Complete!
// finalize

Но нашим началом потока является subject$, который еще не завершен и будет продолжать получать события, даже если середина потока остановлена ​​на полпути EMPTY, поэтому источник должен завершиться, тогда вы получите срабатывание финализации и завершения блока!

import './style.css';

import { Subject, switchMap, tap, finalize, EMPTY } from 'rxjs';

const subject$ = new Subject();

subject$
  .pipe(
    tap(() => console.info('tap1')),
    switchMap(() => EMPTY),
    tap(() => console.info('tap2')),
    finalize(() => console.info('finalize'))
  )
  .subscribe({
    next: () => console.info('next'),
    error: () => console.info('error'),
    complete: () => console.info('complete'),
  });
// emits tap1
// output:
// tap1
subject$.next(null);
// emits tap 1 again eventhough empty was returned
// output:
// tap1
subject$.next(null);
// will complete the observable and give the output
// output:
// complete
// finalize

subject$.complete();

EMPTY.pipe(finalize(() => console.info('finalize'))).subscribe({
  next: () => console.info('Next'),
  complete: () => console.info('Complete!'),
});

// will output
// Complete!
// finalize

Демо-версия Stackblitz

Ответ принят как подходящий

switchMap() выдает complete уведомление только тогда, когда завершается как объединенный Observable, так и исходный Observable.

Поскольку наверху вашей цепочки есть объект, который выдает complete только тогда, когда вы вызываете complete() функцию, switchMap() никогда не завершится.

Более подробный пример: очень распространенный вариант использования switchMap() — объединение асинхронного HTTP-запроса, например, в поле поиска с опережением ввода, например:

fromEvent(this.input.nativeElement, 'keyup')
    .pipe(
        map(event => event.target.value), 
        debounceTime(500),
        switchMap(search => API call goes here),
    )
    .subscribe(res => {
        console.info(res)
    });

Если switchMap() выдало complete уведомление, когда его внутренний Observable завершился (то есть, когда завершился вызов API), то эта цепочка будет выполнять поиск только один раз. Однако fromEvent() никогда не завершается, и поэтому, когда вы продолжаете вводить текст, он будет выполнять последующие вызовы API.

Спасибо. Я упустил тот факт, что исходный наблюдаемый объект также должен завершиться для завершения работы switchMap. Я хотел бы добавить, как я достиг своей цели (ожидаемого результата). Поскольку мой реальный вариант использования — это вызов, сделанный при отправке, в конечном итоге я использовал take(1), чтобы сделать наблюдаемый источник завершенным. Таким образом, когда я возвращаю EMPTY, код переходит непосредственно к финализации для очистки.

Mirco 15.04.2024 19:25

Другие вопросы по теме