Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2.0 - converting promise chaining to Observables

I am converting an NG 1.X service to NG 2.0.

My NG 1.X service has promise chaining (simplified):

dataService.search = function(searchExp) {
      return this.getAccessToken()
      .then(function(accesstoken) {
        var url = $interpolate('https://my-api-url?q={{search}}&{{accesstoken}}')({search: searchExp, accesstoken: accesstoken});
        return $http({
          url: url,
          method: 'GET',
          cache: true
        });
      }).then(function(response) {
        return response.data;
      });
    };

I want to convert search service to be an Angular 2.0 Service, using http and returning Observable. I prefer leaving the getAccessToken service untouched, as an NG 1.X service, which returns a promise.

I was thinking about using Observable.fromPromise on the old "promise" service.

How can I do it? How can I chain those two?

EDIT:

Just to clarify, I want it to be something like this:

dataService.search = function(searchExp) {
 return this.getAccessToken()
        .then(function(accesstoken) {
           //Here I want to use:
           // this.http.get(url).subscribe(() => ...)
          });
        };
like image 378
Yaniv Efraim Avatar asked Dec 24 '15 12:12

Yaniv Efraim


People also ask

Can promise be converted to observable?

The correct pattern to transform a promise into an observable is using defer and from operators: import { defer, from } from 'rxjs'; const observable$ = defer(() => from(myPromise())); Why we need the defer operator? Promises are eager, this means that when called they fire instantly.

How do you use observable instead of promise?

The biggest difference is that Promises won't change their value once they have been fulfilled. They can only emit (reject, resolve) a single value. On the other hand, observables can emit multiple results. The subscriber will be receiving results until the observer is completed or unsubscribed from.

What is equivalent to switchMap in promises?

switchMap is one of the most useful RxJS operators because it can compose Observables from an initial value that is unknown or that change. Conceptually, it is similar to chaining then functions with Promises, but operates on streams (Promises resolve once).

What is the difference between promise and observable in Angular?

Promises deal with one asynchronous event at a time, while observables handle a sequence of asynchronous events over a period of time.


2 Answers

You should make search method return Observable object. Something like this:

dataService.search = function(searchExp) {

    var promise = new Promise((resolve, reject) => {
        this.getAccessToken()
            .then(accesstoken => {
                return this.http.get('data.json')
                    .map(response => response.json())
                    .subscribe(data => resolve(data), err => reject(err))
            })
    });

    return PromiseObservable.create(promise); // Observable.fromPromise(promise)
};
like image 50
dfsq Avatar answered Nov 05 '22 12:11

dfsq


I converted @dfsq's Plunker to beta.0. map() doesn't seem to be available anymore without importing it (but we don't need it here).

import {Component, Injectable} from 'angular2/core';
import {HTTP_PROVIDERS, Http} from 'angular2/http';
import {PromiseObservable} from 'rxjs/observable/fromPromise';

@Injectable()
export class DataService {
  constructor(private _http: Http, private _accessService: AccessService) {} 
  search(searchExp) {
    var promise = new Promise((resolve, reject) => {
      this._accessService.getAccessToken()  // see Plunker for AccessService
        .then(accessToken => {
          return this._http.get('data.json')  // use accessToken here
            .subscribe(res => resolve(res.json()), err => reject(err));
        });
    });
    return PromiseObservable.create(promise);
  }
}
@Component({
  selector: 'my-app',
  providers: [HTTP_PROVIDERS, AccessService, DataService],
  template: `<h2>Data loaded</h2><pre>{{data | json}}</pre>
  `
})
export class AppComponent {
  data: any;
  constructor(private _dataService: DataService) { 
    console.clear();
  } 
  ngOnInit() {
    this._dataService.search('test')
      .subscribe(res => {
        this.data = res; 
      });
  }
}

beta.0 Plunker

like image 41
Mark Rajcok Avatar answered Nov 05 '22 12:11

Mark Rajcok