Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

291
Visualizações
Clear Observable value when calling function

I have a dropdown which gets values from a service.

Dropdown

<mat-select
  *ngIf="selectedCloudTypeName === 'AWS'"
  class="select--width--130"
  [formControl]="awsOwnersControl"
  placeholder="AWS Owners"
  msInfiniteScroll
  (infiniteScroll)="loadMoreAwsOwners()"
  [complete]="currentAwsOwnerssDropdownOffset >= awsOwnersTotalCount"
>
  <mat-option *ngFor="let owner of awsOwners$ | async" [value]="owner.id">
    {{ owner.name }}
  </mat-option>
</mat-select>

Service call in TS file

getAwsOwners(offset = 0) {
this.isLoading$.next(true);
this.awsService
  .getOwnersListForAws(this.selectedCredentialIdForCloudType, this.selectedPlatform, { offset, limit: 100 })
  .subscribe(
    (owners: PaginatedResult<CommonEnumValue[]>) => {
      this.awsOwners.next(owners.data);
      this.awsOwnersTotalCount = owners.totalCount;
      this.isLoading$.next(false);
    },
    (error) => {
      this.isLoading$.next(false);
      this.alertify.error(error);
    },
  );

}

In OnInit hook I use an Observable

this.awsOwners$ = this.awsOwners.asObservable().pipe(scan((acc, curr) => [...acc, ...curr], []));

which I declare on as property in the file as

awsOwners = new BehaviorSubject<CommonEnumValue[]>([]);
awsOwners$: Observable<CommonEnumValue[]>;

The problem is when I call the getAwsOnwers function with different 'selectedPlatform' value, the old data persists and the new data gets appended.

I tried to clear the awsOwners Subject like this

this.awsOwners.next([]);

before I call it but it does clear it and new data gets appended to the old one,

Any ways how can I clear it?

I sense that in the scan operator I some how need to clear the '.acc' because it accumulates the values.

over 4 years ago · Santiago Trujillo
3 Respostas
Responde à pergunta

0

  1. Remove scan from this.awsOwners$ pipe
this.awsOwners$ = this.awsOwners.asObservable()
  1. Make this.selectedPlatform as Subject, and make it call getAwsOwners if changed
this._selectedPlatform$ = new Subject()

get selectedPlatform$() {
  // if platform is object you should provide comparing callback to distinctUntilChanged operator
  return this._selectedPlatform$.asObservable.pipe(distinctUntilChanged(), tap(() =>
    //make getAwsOwners() accept platform as an parameter and offset as a optional one.
    this.getAwsOwners(platform);
 ))
}
  1. Inside getAwsOwners subscribe method make some changes
  .subscribe(
    (owners: PaginatedResult<CommonEnumValue[]>) => {
      // always if offset === 0 you should reset owners state
      this.awsOwners.next(offset ? 
        [...this.awsOwners.getValue(), ...owners.data] : 
        owners.data
      );

      this.awsOwnersTotalCount = owners.totalCount;
      this.isLoading$.next(false);
    },
    (error) => {
      this.isLoading$.next(false);
      this.alertify.error(error);
    },
  );
over 4 years ago · Santiago Trujillo Relatório

0

you could reset your scan if your curr value in the scan lambda is empty.

(acc, curr) => curr === [] ? [] : [...acc, ...curr]

but that would kind of feel dirty to me.


a cleaner way would be to resubscribe to your scan observable once you wish to reset.

you could create a BehaviourSubject and emit every time you wish to reset your value. then you could pipe your subject and switchMap to your scan observable. this way the observable would always resubscribe to your scan observable and thus start over, as switchMap automatically unsubscribes and subscribes if the source emits a value.

could look something like this:

BehaviourSubject resetSubject$ = new BehaviourSubject<void>(); // use behaviour subject to get an initial emit
awsOwners$ = resetSubject$.pipe(
  switchMap(() => this.awsOwners.asObservable().pipe(
    scan((acc, curr) => [...acc, ...curr], [])
  ),
);

// call this to reset your scan
resetSubject$.emit()
over 4 years ago · Santiago Trujillo Relatório

0

Instead of having a method that updates a subject, just create a stream that maintains the state of the list data, if it's loading, and the current page offset.

readonly offsetChangeSubject = new Subject<number>();
readonly selectedPlatformSubject = new Subject<string>();
readonly ownersList$ = this.selectedPlatformSubject.pipe(
  switchMap(platform) => offsetChangeSubject.pipe(
    startWith(0), 
    mergeScan((acc, offset) => 
      this.awsService.getOwnersListForAws(this.credentialId, platform, { offset, limit: 100 }).pipe(
        startWith({ ...acc, isLoading: true, offset })
        map(page => ({ 
          isLoading: false,
          offset,
          owners: owners.concat(page.data), 
          totalCount: page.totalCount 
        }))
      ),
      { isLoading: false, owners: [], totalCount: 0, offset }
    )
  ))
)
  1. The offset and platform arguments are converted into a subjects.
  2. The main observable is created from the platform subject.
  3. The only operator inside the main observable is switchMap. This causes any existing requests to immediately get cancelled.
  4. Inside the switchMap, offsetChanges is subscribed to. It immediately will emit 0 because of the startWith operator.
  5. Any emissions from offsetChanges will immediately kick off the owners request inside the mergeScan. This will use data from the previous emission as well as emit twice for each request so that the loading state is also managed.

Notes

  • If it's not apparent, there will always be a result once platformSubject first emits.

  • I presumed that once that platform changed, you'd want the offset reset as well, that is one of the reasons why I didn't make offsetSubject a BehaviorSubject and instead used startWith to emit 0. So you'd retrieve the current value of the offset from the ownersList$ observable, not the offsetChangeSubject - that's only for updates.

  • You can use shareReplay if you want the current list state in more than just the view.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda