Определите, является ли Observable «выполнимым» - PullRequest
0 голосов
/ 09 ноября 2018

Я часто сталкиваюсь с ситуацией, когда я не могу легко определить, является ли наблюдаемое "выполнимым" или нет. Что я имею в виду под завершаемым? Допустим, у нас есть:

service.ts

...

public getData(): Observable<number[]> {
    // Obviously in real application there would be something more meaningful
    return of([1, 2, 3]);
}

...

component.ts

...

public updateData(): void {
    this.serviceA.getData.subscribe(
        newData => this.data = newData
    );
}

...

В нашем service.ts у нас есть метод getData(), который возвращает данные через Observable и после этого завершается.

Почему я хочу знать, завершится ли это? Потому что, если он завершится, это означает, что мне не нужно отписываться от этого после того, как мой компонент будет уничтожен. Очевидно, что в тривиальных случаях это не имеет большого значения, но если вы работаете в команде над большой кодовой базой, вам каждый раз нужно это выяснять.

Ответы [ 2 ]

0 голосов
/ 09 ноября 2018

Как уже упоминалось, нет никакого способа сделать вывод исключительно по типу Observable, будет ли он завершен в любой момент в будущем или нет.Контракт Observable не включает такую ​​семантику.Тем не менее, я мог бы представить следующие решения:

1: разрешить кому-то другому обрабатывать отписку

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

Вместо того, чтобы подписываться и отписываться, я использую трубку Angular async как можно чаще.В большинстве случаев преобразование данных может быть обработано с помощью Observable pipes таким образом, что все мои промежуточные компоненты просто добавляют каналы, и только компонент представления в конце концов подписывается на результат Observable.Если ваша структура представления еще не поддерживает это, я бы попытался найти плагин или даже реализовать его сам.

Например, вместо того, чтобы присваивать результат наблюдаемого свойству класса, как в вашем примере,Я бы просто использовал шаблон Angular, чтобы подписаться на Observable.Компонент изменен:

public data$: Observable<number[]>;

public updateData(): void {
    // here, modification would take place with pipes
    this.data$ = this.serviceA.getData();
}

И, наконец, в шаблоне я бы использовал async:

<div *ngIf="(data$ | async) as data">
    {{ data }}
<div>

2: введите новый тип

Хотяисходный наблюдаемый контракт не включает семантику для решения вашей проблемы, мы могли бы ввести собственный тип, который будет заключен в Observable, чтобы указать, что эта наблюдаемая в конечном итоге завершится.Чтобы гарантировать такое поведение, мы могли бы добавить тайм-аут, который завершает наблюдаемое, если он не уведомил в течение определенного времени.Это может выглядеть так:

class ShortLivedObservable<T> extends Observable<T> {
    private constructor() {
        super();
    }
}

function asShortLivedObservable<T>(source: Observable<T>, timeout: number = 1000): ShortLivedObservable<T> {
   return source.pipe(
       switchMap(value =>
           merge(
               of(value).pipe(
                   map(value => ({value: value}))
               ),
               timer(timeout).pipe(
                   map(() => ({complete: true}))
               )
           )
       ),
       takeUntil(({value, complete}) => complete),
       map(({value}) => value)
   )
}

Однако это решение будет иметь недостаток, заключающийся в том, что вводятся новые семантики, которые не следуют рекомендациям ReactiveX.Тип должен был бы быть передан конечному потребителю, и дальнейшие трубопроводы могут снова сделать наблюдаемую утечку (см. Проблемы, описанные здесь: RxJS: Избегание takeUntil Leaks ).

0 голосов
/ 09 ноября 2018

По моему мнению, хорошая практика - рассматривать все наблюдаемые как вечные и никогда не "податливые". Не существует прямого способа определения априори конкретной наблюдаемой «податливости», поскольку это полностью зависит от наблюдаемой логики, которая с точки зрения пользователя является частной и относится к наблюдаемой. Вместо того, чтобы делать предположения, лучше хранить каждую подписку в переменной контроллера, а когда контроллер разрушен, просто отмените подписку на все из них, что безопасно даже для уже закрытых подписок.
Если у вас есть конкретные действия, которые нужно выполнить для наблюдаемой полноты, попробуйте реализовать его в обработчике onComplete.

Этот подход заставляет вас рассмотреть все нижеуказанные сценарии:

  • никакое значение не будет выдано, и наблюдаемое будет завершено (пусто)
  • никакое значение не будет выдано, и наблюдаемое не будет завершено (пустое вечное значение)
  • будет выброшено бесконечное количество значений, и наблюдаемые не будут завершены (постоянны)
  • будет выбрано одно или несколько значений, и наблюдаемое будет завершено
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...