2017-02-28 106 views
9

也许我错过了一些东西。我无法找到Observable及其语法的简单教程。我正在使用Angular,我需要从服务中调用一个函数(在一个组件中定义)。我读了solution。但我无法弄清楚如何改变服务中创建的Observable的值(也许创建不是最好的方法)。Typescript Angular - Observable:如何更改其值?

我有一个成分像的解决方案:

@Component({ 
    selector: 'my-component', 
    ... 
)} 
export class MyComponent { 
    constructor(myService:MyService) { 
    myService.condition.subscribe(value => doSomething(value)); 
} 

doSomething(value) { 
    if (value) // do stuff 
    else // other stuff 
} 

}

,这是我的服务:

import { Injectable } from '@angular/core'; 
import { Observable} from 'rxjs/Observable'; 

@Injectable() 

export class MyService { 
    private condition: Observable<boolean>; 
    constructor() { 
     this.condition= new Observable(ob => {ob.next(false); }) 
     // maybe ob.next is not the best solution to assign the value? 
    } 

    change() {// how can i change the value of condition to 'true', to call 
       // the doSomething function in the component?? 
    } 

} 
+0

我无法准确提取您想要执行的操作。你能否给你的问题多一些背景?为什么你(想)你想从一个服务调用一个组件功能? Observable就像是一种承诺:通常用在Component中,当某个异步操作完成时,要求Service返回一个Observable,并在Component(或另一个Service)内部采取行动。 – msanford

+0

您链接的其他问题与使用服务作为两个组件之间的中介相关。这是你想要做的吗? – msanford

+0

'this.condition = Observable.of(false)'为你工作吗? – msanford

回答

4

从关于my other answer的评论(因为它可能对某人有帮助而被保留),您似乎想要利用某些东西的强大功能随着时间的推移

由于DOMZE提出,使用主题,但这里是一个(微不足道)示例如何你可以做到这一点。虽然有明显的some pitfalls to avoid in using Subject directly,但我会留给你的。

import { Component, NgModule } from '@angular/core' 
import { BrowserModule } from '@angular/platform-browser' 
import { Observable, Subject } from 'rxjs/Rx'; 

@Component({ 
    selector: 'my-app', 
    template: ` 
    <div> 
     <h2>Open the console.</h2> 
    </div> 
    `, 
}) 
export class App { 

    constructor() {} 

    let subject = new Subject(); 

    // Subscribe in Component 
    subject.subscribe(next => { 
    console.log(next); 
    }); 

    setInterval(() => { 
    // Make your auth call and export this from Service 
    subject.next(new Date()) 
    }, 1000) 
} 

@NgModule({ 
    imports: [ BrowserModule ], 
    declarations: [ App ], 
    bootstrap: [ App ] 
}) 
export class AppModule {} 

Plunker

在我的愚见,对于这种情况,我不明白为什么一个简单的服务/可观察是不够的,但是这是我的事。

延伸阅读:Angular 2 - Behavior Subject vs Observable?

+1

谢谢!可能对我的问题的解释不是很好(我不是英语),所以感谢您的耐心。我尝试了这个主题,它对我的​​目的(和BehaviorSubject)来说似乎是完美的。 – Johannes

+1

@Johannes对我来说,这也是一个有趣的问题,所以欢迎您! (你的英语非常好,我也来自另一个语言背景;)) – msanford

1

管理登录状态

对于此实现,您只需要一个服务。在它中,你可以让你的后端请求查看用户是否有会话,然后你可以将它保存在服务中的类变量中。然后,如果该变量已设置,则返回该变量,或直接返回REST调用的结果。

例如:

export class AuthenticationService { 

private loggedIn: boolean = null; 

constructor(private http: Http) { } 

getUserSession(credentials): Observable<boolean> { 

    if (this.loggedIn !== null) { 

    return Observable.of(this.loggedIn); 

    } else { 

    return this.http.get('/authenticate?' + credentials) 
     .map((session: Response) => session.json()) 
     .catch(e => { 
     // If a server-side login gate returns an HTML page... 
     return Observable.of(false); 
     }); 

    } 
} 

然后在组件,只需订阅可观察像往常一样,并作用于它的点播。

没有与Observable.share()Observable.replay()实现这一

可观察语法

解答有关的Rx可观察到的Angular2语法问题的一部分,其他的方法(应该有人谷歌它),在一般形式是:

在服务:

return this.http.get("/people", null) 
    .map(res.json()) 
    .catch(console.error("Error in service") 

,且在组件,通过示例的方式:

this.someService.getPeople() 
    .subscribe(
    people => this.people, 
    error => console.warn('Problem getting people: ' + error), 
    () => this.doneHandler(); 
); 

形式上:

interface Observer<T> { 
    onNext(value: T) : void 
    onError(error: Error) : void 
    onCompleted() : void 
} 

接收到“下一个”值时,第一函数被调用。在REST调用的情况下(最常见的情况),这包含整个结果。

第二个函数是错误处理程序(在服务中调用Observable.trow()的情况下)。

当结果集已有并且不带参数时调用最后一个。这是您可以调用doSomething()函数的地方。

+0

谢谢,我正在尝试这种方法。但通常,我想了解一种方法来“告诉”一个组件X,即在服务中变量值被改变;所以,在一个组件中,我想订阅该变量。 – Johannes

+0

@Johannes我明白你的意思了,所以这就是为什么你在使用'Observable.next()',所以你可以使用它几乎就像一个ES6 _ * generator_?或者保持双向数据绑定的精神,但是从服务到组件,而不是组件到视图。想到几个想法不是非常习惯的ng2,但这是一个有趣的问题,所以我会自己检查一下,如果我发现了什么,请发表另一个答案。 – msanford