Subject.subscribe не работает вне конструктора

#javascript #angular #rxjs #angular7

#javascript #угловой #rxjs #angular7

Вопрос:

У меня есть простой сервис.

 import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class XmlService {
    items$: Subject<Item[]> = new Subject<Item[]>();

    constructor() {
        setTimeout(() => this.items.next([{age: '20'}]), 4000);
    }
}
  

После настройки его в app.module.ts и соответствующих файлах я прихожу к app.component.ts , в котором у меня есть следующая настройка:

 @Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css']
})
export class AppComponent {
    constructor(private xmlService: XmlService) {
        // Try 1. It worked fine
        xmlService.items$.subscribe(items => console.log(items));
    }

    calledFromClick() {
        // Try 2. Does not work at all even though the method is clicked
        this.xmlService.items$.subscribe(items => console.log(items));
    }
}
  

Есть ли какая-либо причина, по которой попытка 1 сработала, а попытка 2 не сработала? У меня такое чувство, что этот вопрос является дубликатом другого вопроса, но я не могу понять, как правильно задать этот вопрос.

Рассчитываю на вашу помощь 🤞🏼

Комментарии:

1. вы нажимали в течение первых 4 секунд? Если вы нажали после истечения тайм-аута, вы не получите никаких событий, я думаю

2. можете ли вы вызвать calledFromClick из ngOnInit и повторить попытку, дайте мне знать, работает это или нет

3. @TobiasGassmann. Я нажал путь через 4 секунды

4. Это работает на ngOnInit . Я просто хотел знать, есть ли причина, по которой это не работает вне ngOnInit и constructor

5. Чтобы получать уведомления, вы должны подписаться перед this.items.next() вызовом. В данном случае вы должны подписаться в течение первых 4 секунд, как упоминал Тобиас Гассманн. Попробуйте нажать кнопку раньше или увеличить setTimeout задержку.

Ответ №1:

Редактировать: Сначала я предложил ReplaySubject, но, полагаю, BehaviorSubject был бы лучше

https://medium.com/@luukgruijs/understanding-rxjs-behaviorsubject-replaysubject-and-asyncsubject-8cc061f1cfc0

Вы могли бы использовать BehaviorSubject, подобный этому:

 import { Injectable } from '@angular/core';

@Injectable({ providedIn: 'root' })
export class XmlService {
    items$: BehaviorSubject<Item[]> = new BehaviorSubject<Item[]>();

    constructor() {
        setTimeout(() => this.items.next([{age: '20'}]), 4000);
    }
}
  

BehaviourSubject сохраняет свое последнее значение, так что подписчики всегда будут получать последнее значение, даже если оно было передано до вызова subscribe-метода.