Невозможно прочитать свойство 'next' из неопределенного, используя BehaviorSubject - PullRequest
0 голосов
/ 22 сентября 2019

У меня эта проблема только при развертывании на Android (не пытался на iOS) , если я запускаю ionic serve, чтобы посмотреть, все ли в порядке, консоль не выдаст мне ошибкии работает нормально !, но когда я пытаюсь сделать это в Android, у меня возникает проблема:

Не удается прочитать свойство 'next' из неопределенного

хорошо, давайте сделаем описаниеПрежде всего, я использую встроенный шаблон ионного стартера side_menu, я сделал несколько модификаций стиля (но только это), поэтому давайте рассмотрим каждый компонент, необходимый для воспроизведения этой проблемы:

приложение.component.html :

здесь я только помещаю событие ionDidClose в элемент ion-menu (другие вещи в документе вообще не нужны):

<ion-menu class = "shorted_menu" (ionDidClose) = "setDisplayMenuInfo('basicInfo')">
    <!--More code here...-->
</ion-menu>

в app.component.ts у меня есть:

import { Component } from '@angular/core';
import { Platform } from '@ionic/angular';
import { SplashScreen } from '@ionic-native/splash-screen/ngx';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { enableProdMode } from '@angular/core';
import { MenuController } from '@ionic/angular';

import { Storage } from '@ionic/storage';
import { Router} from '@angular/router';
import { OneSignal } from '@ionic-native/onesignal/ngx';
import { AppPages } from '../global_modules/app_pages';
import { showInfo, setComponentBehaviorSubject } from '../global_modules/menu_functionality';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';

enableProdMode();

@Component({
  selector: 'app-root',
  templateUrl: 'app.component.html'
})

export class AppComponent {

    public appPages;
    public showInfo;
    public currentDisplayMenu = 'basicInfo';
    public behaviorSubject: BehaviorSubject<string>;
    public behaviorSubjectObservable: Observable<any>;
    public behaviorSubjectSubscription: Subscription;
    public setComponentBehaviorSubject;

    constructor(
        private platform: Platform,
        private splashScreen: SplashScreen,
        private statusBar: StatusBar,
        private oneSignal: OneSignal,
        private storage: Storage,
        private router: Router,
        public menu: MenuController
    )
    {
        this.initializeApp();
    }

    async setup(){

        this.appPages = AppPages.pages;
        this.showInfo = showInfo;
        this.setComponentBehaviorSubject = setComponentBehaviorSubject;

        this.userData = await this.getUserData();
        this.userAvatar = this.userData.data.avatar_src.src && this.userData.data.avatar_src.src != "" ? 
                        `${this.imagesRoute}${this.userData.data.avatar_src.src}`:
                        this.userAvatar;

        this.behaviorSubject = new BehaviorSubject<string>('basicInfo');
        this.behaviorSubjectObservable = this.behaviorSubject.asObservable();
        this.setComponentBehaviorSubject(this.behaviorSubject);

        this.behaviorSubjectSubscription = this.behaviorSubjectObservable.subscribe(data =>{

            this.currentDisplayMenu = data;

        });

    }

    ionViewWillLeave(){

        this.behaviorSubjectSubscription.unsubscribe();

    }

    setDisplayMenuInfo(str){

        this.showInfo(str);

    }

    async getUserData(){

        return await this.storage.get('session_storage');

    }

    clearUserSession(){

        this.oneSignal.removeExternalUserId();
        this.storage.set('session_storage', null);

    }

    initializeApp() {
        this.platform.ready().then(() => {
            this.statusBar.styleLightContent();
            this.splashScreen.hide();
            this.setup();

            if(this.platform.is('cordova')){

                this.setupPush();

            }

            this.storage.get('session_storage').then((res)=>{

                if(res == null){

                    this.router.navigateByUrl('log-in');

                }

            });

        });
    }

    setupPush(){

        this.oneSignal.startInit(oneSignalData.appId, oneSignalData.googleProjectNumber);
        this.oneSignal.inFocusDisplaying(this.oneSignal.OSInFocusDisplayOption.Notification);

        this.oneSignal.handleNotificationReceived().subscribe(data => {

            //Do something when notification received...
            /*let msg = data.payload.body;
            let title = data.payload.title;
            let additionalData = data.payload.additionalData;*/

        });

        this.oneSignal.handleNotificationOpened().subscribe(data => {

            let additionalData = data.notification.payload.additionalData;
            //Actions to take when notification opened...

        });

        this.getUserData().then(res =>{

            if(res && res.data.username != "" && res.data.type_user != ""){

                this.oneSignal.setExternalUserId(`${res.data.username};${res.data.type_user}`);

            }else{

                this.oneSignal.removeExternalUserId();

            }

        })

        this.oneSignal.endInit();

    }

}

где AppPages - это просто другой класс, импортированный app.component.ts, а внутри у меня есть открытые страницы статических свойств, это простомассив объектов, и внутри каждого объекта у меня есть некоторая поддержка отображения менюКак и заголовок и значок каждого элемента меню, также с другим свойством, называемым detailTag, этот тег позволяет мне легко отображать или скрывать некоторый контент меню в зависимости от свойства:

currentDisplayMenu

изapp.component.ts, поэтому некоторая информация меню классифицируется как 'basicInfo' внутри свойства detailTag, это означает, что когда currentDisplayMenu имеет содержимое 'basicInfo', я буду показывать только те пункты меню, которые имеют detailTag, совпадающий с 'basicInfo', остальныеКлассификация - это accountInfo.

Ну, другой необходимый файл: menu_functionality.ts , который выглядит так:

import { BehaviorSubject } from 'rxjs';

var componentBehaviorSubject:BehaviorSubject<string>;

export function showInfo(tag){

    switch(tag){

      case 'basicInfo':
        return componentBehaviorSubject.next('basicInfo');
        break;
      case 'accountInfo':
        let CBS = componentBehaviorSubject.next('accountInfo');
        this.menu.open();
        return CBS;
        break;

    }

}

export function setComponentBehaviorSubject(behaviorSubject:BehaviorSubject<string>){

  componentBehaviorSubject = behaviorSubject;

}

Причина, по которой явызывая this.menu.open ();Функция работает только в том случае, если тэг «accountInfo», потому что app.component.html и app.component.ts работают глобально в приложении, и если пользователь нажимает только кнопку бокового меню, чтобы открыть его, проблем нет и нетнужно поставить его, но вот в чем дело и реальная причина того, почему я использую BehaviorSubject:

  • App.component.html и app.component.ts являются общими, поэтому проблем нетесли пользователь нажимает кнопку открывания меню на одной или другой странице приложения, но ... при отображении другой информации, такой как accountInfo, используется аватар, который не находится внутри app.component.html (являетсяне поделился) я хотел поместить в другое место вместо того, чтобы поместить его в меню, потому что я не знал, как сделать его глобально пригодным для использования, как app.component.html, поэтому я должен написать этот HTML на каждой странице.html, что я хочу его использовать.

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

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