Оператор взятия() RxJS

У меня возникли проблемы с пониманием оператора take(). В его определении предполагается, что он возвращает первое значение, испускаемое наблюдаемым, но мне кажется, что оно возвращает последнее.

Я попробовал следующий тест, чтобы понять это лучше:

UsersService.ts

import {User} from '../models/user.model';
import {BehaviorSubject} from 'rxjs';

@Injectable({providedIn: 'root'})
export class UsersService {

  userObs = new BehaviorSubject<{test: string}>(null);

  testEmit(inp: string) {
    this.userObs.next({test: inp});
  }
}

и компонент.

пользователи.component.html

  <div class="row">
    <div class="col-xs-12 col-md-6 col-md-offset-3">
      <input type="text" class="form-control" #inp>
      <button class="btn btn-primary" (click)="testTake(inp)">Emit</button>
    </div>
  </div>
</div> 

пользователи.component.ts

import {Component, Input, OnDestroy, OnInit} from '@angular/core';
import {User} from '../models/user.model';
import {UsersService} from '../services/users.service';
import {interval, Observable, Observer, Subscription} from 'rxjs';
import {take} from 'rxjs/operators';

@Component({
  selector: 'app-users',
  templateUrl: './users.component.html',
  styleUrls: ['./users.component.css']
})
export class UsersComponent implements OnInit, OnDestroy {
  constructor(private usersService: UsersService) {
  }

  ngOnInit(): void {
    this.usersService.userObs.pipe(take(1)).subscribe((data: {test: string}) => {
      console.log(data.test);
    });
  }

  testTake(inp: HTMLInputElement) {
    this.usersService.testEmit(inp.value);
  }
}

В представлении я набираю что-то на входе и нажимаю кнопку, чтобы выдать его, а затем я перехожу к другому компоненту и возвращаюсь к этому, чтобы повторно запустить функцию OnInit(), и то, что я получаю в консоли, - это последнее значение, которое я написал на входе. Я смотрю на это неправильно?

Спасибо за ваше время и помощь.


person Veoxer    schedule 26.07.2020    source источник


Ответы (1)


Это очень очевидно, так как BehaviorSubject имеет свойство хранить «текущее» значение. Это означает, что вы всегда можете напрямую получить последнее сгенерированное значение из BehaviorSubject.

И вы используете одноэлементный сервис. Поэтому, когда вы переходите на другой маршрут и возвращаетесь, он выдает последнее сохраненное значение.

Это может помочь вам лучше понять это

Если это не то, что вам нужно, я бы рекомендовал использовать Subject вместо BehaviourSubject.

person micronyks    schedule 26.07.2020
comment
Спасибо за ваш ответ, поэтому, когда я объединяю take и BehaviorSubject, я получаю только пользу от того факта, что take отменяет подписку сам по себе? - person Veoxer; 26.07.2020
comment
Take — оператор. Он действует на наблюдаемое испускаемое значение. Таким образом, take не может быть unsubscribed, любой наблюдаемый объект может быть отписан. Итак, да, в вашем случае наблюдаемый все еще жив, когда вы переключаетесь между страницами/маршрутами. - person micronyks; 26.07.2020
comment
Итак, если я переключил BehaviorSubject на Subject, я должен получить первое значение независимо от того, сколько значений я испускаю? - person Veoxer; 26.07.2020
comment
Нет, это не значит. Это означает, что если observable испускает streams of data, в этом случае оператор взятия примет first stream data. Если вы испускаете значение через наблюдаемые один за другим. Он будет учитывать все значения. Должно быть streams of data. - person micronyks; 26.07.2020
comment
Итак, массив считается потоком данных, но почему массив, возвращаемый запросом на получение, также не считается потоком данных? - person Veoxer; 27.07.2020