web-dev-qa-db-fra.com

Typescript Angular - Observable: comment changer sa valeur?

Peut-être que je manque 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) depuis un service. Je lis ceci solution . Mais je ne peux pas comprendre comment changer la valeur de l'observable créé dans le service (la création n'est peut-être 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 voici 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?? 
    }

}
27
Johannes

D'après les commentaires sur mon autre réponse (préservé car cela peut être utile à quelqu'un), vous semblez vouloir exploiter le pouvoir de quelque chose pour émettre des valeurs au fil du temps .

Comme DOMZE l'a proposé, utilisez un sujet, mais voici un exemple (trivial) montrant comment vous pouvez le faire. Bien qu'il y ait évidemment quelques pièges à éviter en utilisant Subject directement , je vous laisse le soin de décider.

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

À mon humble avis, pour ce scénario, je ne vois pas pourquoi un simple service/observable ne suffit pas, mais ce n'est pas mon affaire.

Lectures supplémentaires: Angular 2 - Behavior Subject vs Observable?

11
msanford

Je voudrais expliquer comment utiliser Observables au cas où vous voudriez mettre à jour la valeur mais je n’utiliserai pas votre exemple. Je vais simplement 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 souhaitez mettre à jour la valeur d'un observable, vous devez le faire dans la fonction 'create'. Cela sera possible si vous déclarez une fonction dans cette fonction 'create'.

6
EA0906

Je vous suggère de changer votre condition pour devenir un sujet. Le sujet est à la fois observateur et observable. Vous pourrez alors émettre une valeur.

Voir https://github.com/Reactive-Extensions/RxJS/blob/master/doc/gettingstarted/subjects.md

3
DOMZE

Gestion de l'état de connexion

Pour cette implémentation, vous n'avez besoin que d'un seul service. Dans celle-ci, vous feriez votre demande principale pour voir si l'utilisateur avait une session, et vous pourrez ensuite l'enregistrer dans une variable de classe du service. Ensuite, renvoyez cette variable si elle est définie ou renvoyez le résultat d'un appel REST directement).

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, abonnez-vous à l'Observable comme d'habitude et agissez à la demande.

Il existe d’autres méthodes pour y parvenir avec Observable.share() et Observable.replay()

Syntaxe observable

Pour répondre à une partie de la question concernant la syntaxe d'un observateur Rx dans Angular2 (si quelqu'un le recherche sur Google), la forme générique est la suivante:

Dans un service:

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

Et dans un composant, à titre d'exemple:

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

Officiellement:

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

La première fonction est appelée lorsque la valeur "next" est reçue. Dans le cas d'appels REST (cas le plus courant)), le résultat est complet.

La deuxième fonction est un gestionnaire d’erreur (dans le cas, Observable.trow () a été appelé dans le service).

Le dernier est appelé lorsque le jeu de résultats était a et ne prend aucun paramètre. C’est là que vous pouvez appeler votre fonction doSomething ().

2
msanford