How to create an Observable from static data similar to http one in Angular?

TypescriptPromiseAngularObservableRxjs

Typescript Problem Overview


I am having a service that has this method:

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

in the component's constructor I am subscribing like this:

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

This works if an object comes from the server but I am trying to create an observable that will work with the given subscribe() call for a static string (this happens when testModelService.fetchModel() does not receive an uuid) so there is seamless handling in both cases.

Typescript Solutions


Solution 1 - Typescript

Perhaps you could try to use the of method of the Observable class:

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

Solution 2 - Typescript

As of July 2018 and the release of RxJS 6, the new way to get an Observable from a value is to import the of operator like so:

import { of } from 'rxjs';

and then create the observable from the value, like so:

of(someValue);

Note, that you used to have to do Observable.of(someValue) like in the currently accepted answer. There is a good article on the other RxJS 6 changes here.

Solution 3 - Typescript

Things seem to have changed since 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());
  }
}

The .next() function will be called on your subscriber.

Solution 4 - Typescript

This is how you can create a simple observable for static data.

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

I hope this answer is helpful. We can use HTTP call instead static data.

Solution 5 - Typescript

This way you can create Observable from data, in my case I need to maintain shopping cart:

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

Solution 6 - Typescript

As of May 2021 the new way to get an Observable from a value is:

importing:

import "rxjs/add/observable/of"
import { Observable } from "rxjs/Observable"

and using, like so::

Observable.of(your_value)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichail MichailidisView Question on Stackoverflow
Solution 1 - TypescriptThierry TemplierView Answer on Stackoverflow
Solution 2 - TypescriptVSOView Answer on Stackoverflow
Solution 3 - TypescriptNiel de WetView Answer on Stackoverflow
Solution 4 - TypescriptBalwant PadwalView Answer on Stackoverflow
Solution 5 - TypescriptRahul DadhichView Answer on Stackoverflow
Solution 6 - TypescriptdaniloView Answer on Stackoverflow