我们可以直接在Angular 4组件中订阅RxJs主题吗?

时间:2018-06-13 05:18:24

标签: angular typescript service rxjs observable

我有一个Angular服务,我从后端获取数据。现在在这个服务中,我有一个ReplaySubject类型的变量。我将此ReplaySubject变量订阅到我的component

我的代码

@Injectable()
export class PersonService {
    // The person subject
    personStream: ReplaySubject<Person> = new ReplaySubject();

    // Get person from DB and add to stream
    getDataFromDB() {
        this.http.get(url).subscribe(response => {
            this.personStream.next(response.person);
        });
    }
}

@Component({...})
export class MyComponent implements OnInit {
    person: Person;

    constructor(private personService: PersonService) {}

    ngOnInit() {
        this.personService.personStream.subscribe(person => this.person = person);
    }
}

此代码工作正常,但我有疑问。我见过一个与这种方法略有不同的代码。订阅ReplaySubject的另一种方法是在服务中创建一个类型为Observable的新函数,并在组件内部订阅该函数,而不是直接订阅ReplaySubject

示例

@Injectable()
export class PersonService {
    // The person subject
    personStream: ReplaySubject<Person> = new ReplaySubject();

    // The person observable
    person$(): Observable<Person> {
        return this.personStream.asObservable();
    }

    // Get person from DB and add to stream
    getDataFromDB() {
        this.http.get(url).subscribe(response => {
            this.personStream.next(response.person);
        });
    }
}

@Component({...})
export class MyComponent implements OnInit {
    person: Person;

    constructor(private personService: PersonService) {}

    ngOnInit() {
        // Subscribe to person observable. Any time person data changes, this will be called.
        this.personService.person$().subscribe(person => this.person = person);
    }
}

我知道代码的工作方式,但我想知道最好和最有效的方法。

感谢。

2 个答案:

答案 0 :(得分:0)

直接订阅ReplaySubject就好了,正如您在第一种方法中描述的那样。

\{\/\/[^\/{}\s]*\/[^\/{}\s]*\} 进行观察并订阅它(您的第二种方法)有一个好处。您不能将String input = "@process_id={//data/process_id}#@history_id={//data/history_id}#@Pdataxml={//data/dataxml}#@Prules =_UNESCAPEXMLVALUE({//data/rules})#@submitted_by={//data/submitted_by}#@table_definition={//data/table_definition}"; List<String> allMatches = new ArrayList<String>(); Matcher m = Pattern.compile("\\{\\/\\/[^\\/{}\\s]*\\/[^\\/{}\\s]*\\}").matcher(input); while (m.find()) { allMatches.add(m.group()); } System.out.println(allMatches); 值意外地视为可观察对象,但如果[{//data/process_id}, {//data/history_id}, {//data/dataxml}, {//data/rules}, {//data/submitted_by}, {//data/table_definition}] (例如activejdbc.properties)有可能。这是一些额外的安全性,可以节省一些代码。

答案 1 :(得分:0)

第一种方法是当你想从api获取数据并在你的组件中使用它时你只有一个主题在组件中订阅它,假设你有一个超级主题从api获取数据你有一些主题也是这个超级主题的观察者,他们订阅超级主题并对数据进行更改,naxt()将其更改给他们的观察者,例如,您有多个组件,这些组件具有需要数据的多个元素,组件从中获取数据超级主题并订阅它和next()它们的元素。例如:

public registerObserver(name): Observable<any> {
    return this.observers[dataSourceName].observable.map((data: any) => {...}).catch((error: any) => {
        return Observable.throw({ error, name });
    });
}

public storeData(name, observable) {
    observable.subscribe(data => {
        if (this.observers[name]) {
            this.observers[name].subject.next(data);
        }
    }, error => {
        if (this.observers[name]) {
            this.observers[name].subject.error(error);
        }
    });
}