Comment créer un observable à partir de données statiques similaires à http dans Angular?

121

J'ai un service qui a cette méthode:

export class TestModelService {

    public testModel: TestModel;

    constructor( @Inject(Http) public http: Http) {
    }

    public fetchModel(uuid: string = undefined): Observable<string> {
        if(!uuid) {
            //return Observable of JSON.stringify(new TestModel());
        }
        else {
            return this.http.get("http://localhost:8080/myapp/api/model/" + uuid)
                .map(res => res.text());
        }
    }
}

dans le constructeur du composant, je m'abonne comme ceci:

export class MyComponent {
   testModel: TestModel;
   testModelService: TestModelService;

   constructor(@Inject(TestModelService) testModelService) {
      this.testModelService = testModelService;

      testService.fetchModel("29f4fddc-155a-4f26-9db6-5a431ecd5d44").subscribe(
          data => { this.testModel = FactModel.fromJson(JSON.parse(data)); },
          err => console.log(err)
      );
   }
}

Cela fonctionne si un objet provient du serveur mais j'essaie de créer un observable qui fonctionnera avec l' subscribe()appel donné pour une chaîne statique (cela se produit lorsque testModelService.fetchModel()ne reçoit pas d'uuid), donc il y a une gestion transparente dans les deux cas.

Michail Michailidis
la source

Réponses:

151

Vous pourriez peut-être essayer d'utiliser la ofméthode de la Observableclasse:

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';

public fetchModel(uuid: string = undefined): Observable<string> {
  if(!uuid) {
    return Observable.of(new TestModel()).map(o => JSON.stringify(o));
  }
  else {
    return this.http.get("http://localhost:8080/myapp/api/model/" + uuid)
            .map(res => res.text());
  }
}
Thierry Templier
la source
2
C'était génial! Ça a marché! J'essayais beaucoup de choses comme Observable.from () etc. La documentation de l'API pour Observable n'est pas la plus propre / la plus conviviale à ce stade! Merci :)
Michail Michailidis
45
Une chose si vous utilisez la version 6, vous devez import { of } from 'rxjs';et utilisez of, au lieu de Observable.of.
vip
2
Pour Angular v7.xx il n'y a pas .map()de résultat sur get, vous devez donc le faire .pipe(map((res:any) => res.json())). Voir ici: stackoverflow.com/a/35220045/986160
Michail Michailidis
64

Depuis juillet 2018 et la sortie de RxJS 6, la nouvelle façon d'obtenir un observable à partir d'une valeur consiste à importer l' ofopérateur comme suit:

import { of } from 'rxjs';

puis créez l'observable à partir de la valeur, comme ceci:

of(someValue);

Notez que vous deviez faire Observable.of(someValue)comme dans la réponse actuellement acceptée. Il y a un bon article sur les autres changements de RxJS 6 ici .

VSO
la source
Merci beaucoup, cela fonctionne
Sarah
19

Les choses semblent avoir changé depuis Angular 2.0.0

import { Observable } from 'rxjs/Observable';
import { Subscriber } from 'rxjs/Subscriber';
// ...
public fetchModel(uuid: string = undefined): Observable<string> {
  if(!uuid) {
    return new Observable<TestModel>((subscriber: Subscriber<TestModel>) => subscriber.next(new TestModel())).map(o => JSON.stringify(o));
  }
  else {
    return this.http.get("http://localhost:8080/myapp/api/model/" + uuid)
            .map(res => res.text());
  }
}

La .next()fonction sera appelée sur votre abonné.

Niel de Wet
la source
2
J'ai migré vers Angular 2.1.2 .. L'ancienne méthode semble toujours prise en charge. Pourriez-vous s'il vous plaît expliquer pourquoi c'est une meilleure solution ou est-ce la convention? Je le changerai ensuite à tous les endroits de mon code et je le réaccepterai .. Merci
Michail Michailidis
7
@MichailMichailidis, avec un mois de rétrospective, il me semble que les deux sont également valables, la principale différence étant que la solution de Thierry vous oblige à importer la offonction de rxjs, commeimport 'rxjs/add/observable/of'
Niel de Wet
12

C'est ainsi que vous pouvez créer une simple observable pour les données statiques.

let observable = Observable.create(observer => {
  setTimeout(() => {
    let users = [
      {username:"balwant.padwal",city:"pune"},
      {username:"test",city:"mumbai"}]

    observer.next(users); // This method same as resolve() method from Angular 1
    console.log("am done");
    observer.complete();//to show we are done with our processing
    // observer.error(new Error("error message"));
  }, 2000);

})

to subscribe to it is very easy

observable.subscribe((data)=>{
  console.log(data); // users array display
});

J'espère que cette réponse est utile. Nous pouvons utiliser l'appel HTTP à la place des données statiques.

Balwant Padwal
la source
pouvez-vous mettre à jour la faute de frappe de observable.subscripe à observable.subscribe
Sudharshan
3

De cette façon, vous pouvez créer Observable à partir de données, dans mon cas, je dois gérer le panier:

service.ts

export class OrderService {
    cartItems: BehaviorSubject<Array<any>> = new BehaviorSubject([]);
    cartItems$ = this.cartItems.asObservable();

    // I need to maintain cart, so add items in cart

    addCartData(data) {
        const currentValue = this.cartItems.value; // get current items in cart
        const updatedValue = [...currentValue, data]; // push new item in cart

        if(updatedValue.length) {
          this.cartItems.next(updatedValue); // notify to all subscribers
        }
      }
}

Component.ts

export class CartViewComponent implements OnInit {
    cartProductList: any = [];
    constructor(
        private order: OrderService
    ) { }

    ngOnInit() {
        this.order.cartItems$.subscribe(items => {
            this.cartProductList = items;
        });
    }
}
Rahul Dadhich
la source