Come creare un osservabile da dati statici simile a quello http in Angular?


121

Sto avendo un servizio che ha questo metodo:

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());
        }
    }
}

nel costruttore del componente mi sto iscrivendo in questo modo:

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)
      );
   }
}

Funziona se un oggetto proviene dal server ma sto cercando di creare un osservabile che funzioni con la subscribe()chiamata data per una stringa statica (questo accade quando testModelService.fetchModel()non riceve un uuid) quindi c'è una gestione senza soluzione di continuità in entrambi i casi.

Risposte:


151

Forse potresti provare a usare il ofmetodo della 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());
  }
}

2
È stato fantastico! Ha funzionato! Stavo provando molte cose come Observable.from () ecc. La documentazione API per Observable non è la più pulita / user-friendly a questo punto! Grazie :)
Michail Michailidis

45
Una cosa se stai usando la versione 6, devi import { of } from 'rxjs';usare of, invece di Observable.of.
vip

2
Per Angular v7.xx non c'è .map()il risultato di get, quindi devi farlo .pipe(map((res:any) => res.json())). Vedi qui: stackoverflow.com/a/35220045/986160
Michail Michailidis

64

A partire da luglio 2018 e dal rilascio di RxJS 6, il nuovo modo per ottenere un osservabile da un valore è importare l' ofoperatore in questo modo:

import { of } from 'rxjs';

e quindi creare l'osservabile dal valore, in questo modo:

of(someValue);

Nota che dovevi fare lo Observable.of(someValue)stesso nella risposta attualmente accettata. C'è un buon articolo sugli altri cambiamenti di RxJS 6 qui .


Grazie mille, funziona
Sarah

19

Le cose sembrano essere cambiate da 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()funzione sarà chiamata sul tuo abbonato.


2
Sono migrato ad Angular 2.1.2 .. Il vecchio modo sembra essere ancora supportato .. Potresti spiegare perché questa è una soluzione migliore o è la convenzione? Lo cambierò in tutti i punti del mio codice e lo accetterò di nuovo .. Grazie
Michail Michailidis

7
@MichailMichailidis, con un mese di retrospettiva, mi sembra che entrambi siano ugualmente validi, la differenza principale è che la soluzione di Thierry richiede di importare la offunzione di rxjs, comeimport 'rxjs/add/observable/of'
Niel de Wet

12

In questo modo è possibile creare un semplice osservabile per dati statici.

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
});

Spero che questa risposta sia utile. Possiamo usare la chiamata HTTP invece di dati statici.


puoi aggiornare l'errore di battitura da Observable.subscripe a
Observable.subscribe

3

In questo modo puoi creare Observable dai dati, nel mio caso ho bisogno di mantenere il carrello:

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;
        });
    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.