Tapuscrit Angulaire Observables: comment faire pour modifier sa valeur?
Peut-être que je suis absent quelque chose. Je ne trouve pas de tutoriel simple pour Observable et sa syntaxe. Je travaille avec Angular, je dois appeler une fonction (définie dans un composant) à partir d'un service. Je viens de lire ce solution. Mais je ne peux pas comprendre comment changer la valeur dans L'Observable créé dans le service (peut-être la création n'est pas la meilleure méthode).
j'ai un composant comme dans la solution:
@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
}
}
et c'est mon service:
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??
}
}
4 réponses
Dans les commentaires mon autre réponse (conservée, car elle peut être utile à quelqu'un), vous semblez vouloir tirer parti de la puissance de quelque chose d'émettre des valeurs au fil du temps.
comme DOMZE l'a proposé, utilisez un sujet, mais voici un exemple (trivial) montrant comment vous pourriez le faire. Bien qu'il existe de toute évidence quelques pièges à éviter dans l'utilisation directe du sujet, je laisse cela à vous.
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 {}
à mon humble avis, pour ce scénario, Je ne vois pas pourquoi un simple Service/Observable ne suffit pas, mais ce ne sont pas mes affaires.
autres lectures:Angulaire 2 - le Comportement de l'Objet vs Observables?
je vous suggère de changer votre état d'être un Sujet. Le sujet est à la fois observateur et observable. Vous serez alors en mesure d'émettre une valeur.
voir https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/subjects.md
gestion de l'état de connexion
pour cette implémentation, vous n'avez besoin que d'un seul Service. En lui, vous devriez faire de votre backend demande pour voir si l'utilisateur a une session, et ensuite vous pouvez l'enregistrer dans une variable de classe dans le Service. Ensuite, retournez cette variable si elle est définie, ou retournez directement le résultat d'un appel REST.
Par exemple:
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);
});
}
}
et puis dans la composante, il suffit de souscrire à L'Observable comme d'habitude et d'agir sur elle sur la demande.
il existe d'autres méthodes pour y parvenir avec Observable.share()
et Observable.replay()
Syntaxe Observable
Pour répondre à la partie de la question concernant la syntaxe d'une Rx Observables dans Angular2 (si quelqu'un Google), la forme générique est:
dans un Service:
return this.http.get("/people", null)
.map(res.json())
.catch(console.error("Error in service")
Et dans un Composant, par exemple:
this.someService.getPeople()
.subscribe(
people => this.people,
error => console.warn('Problem getting people: ' + error),
() => this.doneHandler();
);
Formellement:
interface Observer<T> {
onNext(value: T) : void
onError(error: Error) : void
onCompleted() : void
}
le la première fonction est appelée lorsque le "prochain" de la valeur est reçu. Dans le cas des appels REST (cas le plus courant), cela contient le résultat complet.
la seconde fonction est un gestionnaire d'erreurs (dans le cas Observable.trow() a été appelé dans le service).
Le dernier est appelé lorsque le résultat a été, et ne prend pas de paramètres. C'est ici que vous pouvez appeler votre fonction doSomething ().
je voudrais expliquer comment utiliser les Observables dans le cas où vous voulez mettre à jour la valeur mais je n'utiliserai pas votre exemple. Je vais juste montrer quelques lignes de code écrites en ES5 avec des explications.
var updateObservable; // declare here in order to have access to future function
var observable = rx.Observable.create(function (observer) {
observer.next(1);
observer.next(2);
observer.next(3);
// attach a function to the variable which was created in the outer scope
// by doing this, you now have your 'updateObservable' as a function and the reference to it as well
// You will be able to call this function when want to update the value
updateObservable = function (newValue) {
observer.next(newValue);
observer.complete();
};
});
// Suppose you want to update on click. Here actually can be whatever (event) you want
vm.click = function () {
// you can call this function because you have a reference to it
// and pass a new value to your observable
updateObservable(4);
};
// your subscription to changes
observable.subscribe(function(data) {
// after 'click' event will be performed, subscribe will be fired
// and the '4' value will be printed
console.log(data);
});
l'idée principale ici est que si vous voulez mettre à jour la valeur D'un Observable, vous devez le faire à l'intérieur de la fonction 'create'. Cela sera possible si vous déclarez une fonction à l'intérieur de cette fonction 'create'.