2

As I understand Angular 2 services, if you inject one at the root component, all child components share the same instance of that service.

I have a logging service that I want to use in my decorators and application. But I want to reuse the existing service instance from the root component.

Right now if I put a debugger statement in the logging service constructor, my service is instantiated multiple times. I'm using the ReflectiveInjector, but I think that it's creating a new instance, instead of using the global one.

Maybe I'm going about this wrong or I have a lack of understanding. My reasons for doing this is because I have an observable stream in the logging service, and multiple instances creates multiple observables.

@Injectable()
export class LoggerService {

    private _applicationLog$: ReplaySubject<string>;
    get applicationLog$(): Observable<string> {
        return this._applicationLog$.asObservable();
    }

    constructor(private $localStorage: LocalStorageService, private $appSettings: AppSettings) {
        this._applicationLog$ = <ReplaySubject<string>>new ReplaySubject();
    }

    log(s: string){
       //log to a file and push into the stream
       this._applicationLog$.next(s);
    }
}

Now this is my logging decorator

var injector = ReflectiveInjector.resolveAndCreate([LocalStorageService, AppSettings]);
var service = <LoggerService>injector.resolveAndInstantiate(LoggerService);
var appSettings = <AppSettings>injector.resolveAndInstantiate(AppSettings);

function getTime() {
    let now = new Date();
    let min = ("00" + now.getMinutes()).substr(-2, 2);
    let hours = ("00" + now.getHours()).substr(-2, 2);
    return `${hours}:${min}`;
}

function log(message) {
    service.log(`[${getTime()}] ${message}`);
}

export function Trace() {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        if (AppSettings.logSeverity !== LogSeverity.Trace) return;
        log(`TRACE ${propertyKey}.enter()`);
    };
}

Now I have a component to read the logs

@Component({
    templateUrl: 'applicationlogs.template.html'
})
export class ApplicationLogsPage implements OnInit {
    logs: string[];
    private subscription: Observable<string>;
    constructor(private navCtrl: NavController, private $loggerService: LoggerService) { }

    ngOnInit(){
        this.subscription = this.$loggerService.applicationLog$.subscribe((s) => {
            this.logs = s.split(/\r\n|\r|\n/g);
        });
    }
}
Kim Kern
  • 54,283
  • 17
  • 197
  • 195
Matt
  • 6,264
  • 10
  • 54
  • 82
  • 3
    You can't. You can save a reference to root injector similarly to that https://stackoverflow.com/questions/39409328/storing-injector-instance-for-use-in-components . – Estus Flask Dec 09 '16 at 06:14
  • @estus Well this is better than nothing. Thanks – Matt Dec 09 '16 at 23:55

0 Answers0