Jak utworzyć Observable z danych statycznych, podobnie jak http w Angular?


121

Mam usługę, która ma tę metodę:

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

w konstruktorze komponentu subskrybuję w ten sposób:

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

Działa to, jeśli obiekt pochodzi z serwera, ale próbuję utworzyć obserwowalny, który będzie działał z podanym subscribe()wywołaniem statycznego ciągu (dzieje się tak, gdy testModelService.fetchModel()nie otrzymuje uuid), więc w obu przypadkach jest bezproblemowa obsługa.

Odpowiedzi:


151

Być może mógłbyś spróbować użyć ofmetody Observableklasy:

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
To było niesamowite! Zadziałało! Próbowałem wielu rzeczy, takich jak Observable.from () itp. Dokumentacja API dla Observable nie jest obecnie najczystsza / najbardziej przyjazna dla użytkownika! Dzięki :)
Michail Michailidis

45
Jedna rzecz, jeśli używasz wersji 6, musisz import { of } from 'rxjs';i używać ofzamiast Observable.of.
vip

2
W przypadku Angular v7.xx nie ma .map()wyniku get, więc musisz to zrobić .pipe(map((res:any) => res.json())). Zobacz tutaj: stackoverflow.com/a/35220045/986160
Michail Michailidis

64

Od lipca 2018 r. I premiery RxJS 6nowego sposobu uzyskania Observable z wartości jest zaimportowanie ofoperatora w następujący sposób:

import { of } from 'rxjs';

a następnie utwórz obserwowalne z wartości, na przykład:

of(someValue);

Zwróć uwagę, że Observable.of(someValue)w aktualnie zaakceptowanej odpowiedzi musiałeś postępować podobnie. Jest dobry artykuł na innych RxJS 6 zmian tutaj .


Dziękuję bardzo, to działa
Sarah

19

Wydaje się, że sytuacja uległa zmianie od czasu 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());
  }
}

.next()Funkcja zostanie wywołana na abonenta.


2
Migrowałem do Angulara 2.1.2. Wydaje się, że stary sposób jest nadal obsługiwany .. Czy mógłbyś wyjaśnić, dlaczego jest to lepsze rozwiązanie, czy jest to konwencja? Następnie zmienię to we wszystkich miejscach w moim kodzie i ponownie zaakceptuję .. Dzięki
Michail Michailidis

7
@MichailMichailidis, z miesięczną retrospekcją, wydaje mi się, że oba są równie ważne, główna różnica polega na tym, że rozwiązanie Thierry'ego wymaga zaimportowania offunkcji rxjs, na przykładimport 'rxjs/add/observable/of'
Niel de Wet

12

W ten sposób można utworzyć proste obserwowalne dla danych statycznych.

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

Mam nadzieję, że ta odpowiedź jest pomocna. Zamiast danych statycznych możemy użyć wywołania HTTP.


czy możesz zaktualizować literówkę z
observable.subscripe

3

W ten sposób możesz stworzyć Observable z danych, w moim przypadku muszę prowadzić koszyk:

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;
        });
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.