问题
I have this component listening for messages from a service. Note that every console.log() statement shown below is hit at least once, everything gets logged. That is, except "adding message to array" - that does not get logged, but it should get logged!
Here is the component:
import {Component, OnInit, Inject} from '@angular/core';
import {ChromeDataService} from '../../../../shared/services/events';
@Component({
providers: [ChromeDataService],
selector: 'app-events-list',
templateUrl: './events-list.component.html',
styleUrls: ['./events-list.component.scss']
})
export class EventsListComponent implements OnInit {
isShowEventsList = false;
events = [];
constructor(private data: ChromeDataService) {
console.log('events list component is constructed.');
}
ngOnInit() {
console.log('events list component ngOnInit called.');
this.data.currentMessage.subscribe(message => {
console.log('adding message to array: ', message);
this.events.push(message);
})
}
showEventsList() {
this.isShowEventsList = true;
}
hideEventsList() {
this.isShowEventsList = false;
}
}
here is the data source (an Angular service):
///<reference types="chrome"/>
import {Injectable, Component, Inject} from '@angular/core';
import {ReplaySubject} from "rxjs/ReplaySubject";
@Injectable()
export class ChromeDataService {
private messageSource = new ReplaySubject<Object>();
public currentMessage = this.messageSource.asObservable();
private isListening: boolean = false;
private listener: any;
constructor() {
const self = this;
this.listener = function (msg, sender, sendResponse) {
const parsed = JSON.parse(msg);
console.log('extension received a message:', parsed);
self.changeMessage(parsed);
};
}
changeMessage(message: Object) {
this.messageSource.next(message);
}
stopListening() {
this.isListening = false;
chrome.runtime.onMessage.removeListener(this.listener);
}
startListening() {
this.isListening = true;
chrome.runtime.onMessage.addListener(this.listener);
}
}
does anyone know why when changeMessage()
is called, that the subscribe()
callback does not get invoked?
One big hint is that when I use new BehaviorSubject<Object>('initial');
instead of new Subject<Object>()
- then initial
does arrive and 'adding message to array' is logged.
回答1:
I monkey patched Chrome Messaging API with NgZone to update the view when app gets the response back from background page via chrome.runtime.sendMessage
OR chrome.runtime.onMessage
.
Here is the service I used in my chrome extension.
import { Injectable, NgZone } from "@angular/core";
import { Subject } from "rxjs/Subject";
import { Observable } from "rxjs/Observable";
/*
NgZone monkey patched chrome messaging service.
*/
@Injectable()
export class ChromeMsgSrv {
constructor(private _ngZone: NgZone) { }
public send(msg: any, cb: (resp: any) => any) {
chrome.runtime.sendMessage(msg, (resp: any) => {
this._ngZone.run(() => cb(resp))
})
}
public onMsg(cb: (msg: any) => any) {
chrome.runtime.onMessage.addListener((msg: any) => {
this._ngZone.run(() => cb(msg))
})
}
}
@Olegzandr, I got here on this thread from DevKit.life
. I wanted to contact you for the solution to this problem but couldn't found any contact-us page on your website (assuming Devkit.life is yours). Also, the backlink to this post is in a plain text and not an anchor or clickable element. Hopefully, you would correct these issue present on your website.
回答2:
In short, because I was calling providers:[ChromeDataService]
in more than one place, my service was being created more than once. So I was subscribing to the wrong service.
See:
@Injectable service does not seem to be a singleton
回答3:
Try this:
changeMessage = (message : Object) => {}
And use Subject
instead of replay
.
来源:https://stackoverflow.com/questions/48143275/component-cannot-subscribe-to-data-source