RxJS ReplaySubject не воспроизводится на Ionic2

#angular #ionic2 #rxjs5

#angular #ionic2 #rxjs5

Вопрос:

Я использую Ionic2 / RC0 и внедряю пользовательский сервис для своего приложения.

 @Injectable()
export class UserService {
    UserWhatever: ReplaySubject<User> = new ReplaySubject<User>();



    constructor(private _util: UtilService,
        private _app: AppService,
        private _http: Http) {
        console.log("I am UserService. Just got created")

        this.UserWhatever.subscribe(
            (data) => {
                console.log("User service got a USER");
            }
        )


    }

    login(element) {
        return this.getToken(element).flatMap(
            (data) => {
                return Observable.forkJoin([Observable.of(data),
                this.readUser(data)
                ]);
            }
        ).map(data => {
            localStorage["jwt"] = data[0];
            this._util.sendToast("logged");
            console.log("Http call received a USER")
            let guser: User = data[1];
            console.log("Called next ")
            this.UserWhatever.next(guser)
        });
    }
  

Как только я получил полный ответ от login(), наблюдаемый внутри моего HomeComponent, я отправляю пользователя в DashboardComponent

 export class LoginComponent implements OnInit {

    subs() {
        this._user.UserWhatever.subscribe(
            (data) => {
                console.log("Login Component got a Replayed USER");
            })
    }


    login() {
        this.isDisabled = true;
        this._user.login(this.loginForm)
            .subscribe(
            data => {
                this.subs()   
                this.nav.push(DashboardPageComponent);
            }    
    }
  

Где я подписываюсь на ReplaySubject из моего пользовательского сервиса. Здесь возникают проблемы.Он не воспроизводит объект к моменту его подписки. Все работает нормально, если я снова вызову next() для ReplaySubject.

 export class DashboardPageComponent implements OnInit, OnDestroy, AfterViewInit {
    public user: User;


    constructor(private _app: AppService,
        private _device: DeviceService,
        private _user: UserService,
        private _store: Store<any>,
        private _nav: NavController) {
        console.log("Dashboard component")
    }

    ngOnInit() {

        this._user.UserWhatever.subscribe(
            (data) => {
                this.user = data;
                console.log("Dashboard finally received a User")
                console.log(data)
            }
        )
    }
  

Все это работает как обычный Rxjs.Subject(), но мне нужна функция воспроизведения. Я на rxjs.бета-версия-12

Обновленные журналы

 I am UserService. Just got created
Angular 2 is running in the development mode. Call enableProdMode() to enable the production mode.
Native: tried calling StatusBar.styleDefault, but Cordova is not available. Make sure to include cordova.js or run in a device/simulator
Http call received a USER
Called next 
User service got a USER
Login Component got a Replayed USER
I am UserService. Just got created
Dashboard component
  

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

1. Мне нравится заголовок вопроса ....doesn't replay …;) он, он!!!

2.Вы уверены, что один и тот же UserService экземпляр вводится в DashboardPageComponent и LoginComponent ? Возможно ли DashboardPageComponent получить новый экземпляр (и, следовательно, новый пустой ReplaySubject )?

3. @Brandon Как я могу быть уверен? Я импортирую из того же файла, если это то, что вы имеете в виду. Я почти уверен, что это то, что происходит, но не знаю почему. Подписки работают, если я случайно вызываю next впоследствии

4. поместите консоль. запишите инструкцию в конструкторе UserService и посмотрите, сколько раз она печатается.

5. @Brandon выглядит как this.nav.push(DashboardPageComponent); создание другого другого пользовательского сервиса при его создании. Это должно произойти?

Ответ №1:

Основываясь на вашем коде (который по сути верен) и тестировании, ваша проблема заключается в том, что UserService он воссоздается для каждого компонента, который в нем нуждается. Вам нужно сделать его «одноэлементным сервисом», что просто означает, что один экземпляр будет предоставлен всем компонентам, которые в нем нуждаются.

Я не знаком с Ionic. Вот один поток, который вы можете попробовать. Если это не поможет, я предлагаю вам открыть второй вопрос SO, в котором спрашивается, как сделать ваш UserService одноэлементным в Ionic.

По-видимому, изменение вашего DashboardPageComponent конструктора, чтобы объявить _user свойство общедоступным, а не частным, позволит Ionic вводить тот же экземпляр вместо создания нового. https://forum.ionicframework.com/t/rc0-typescript-private-vs-public-keyword/64863

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

1. Теперь понял! constructor(private _user:UserService) должно быть constructor(public _user:UserService) . Если вы хотите отредактировать свой ответ, чтобы добавить это, я бы принял как правильный ответ

2. Я переименовал вопрос, чтобы он был специфичным для Ionic2

3. forum.ionicframework.com/t/…

4. @CESCO хорошо, я добавил абзац, который, надеюсь, отражает то, что вы обнаружили.