2016-07-26 7 views
0

Ich versuche gerade einige gute alte $ http Promises in rxJs Observablen in angular2 umzuwandeln.Promise Chaining/Cascading zu RxJS eckig 1 zu eckig 2

Ein sehr einfaches Beispiel für etwas, das ich in Winkel 1 häufig zu tun pflegte:

// Some Factory in Angular 1 
var somethings = []; 
var service = { 
    all: all 
}; 
return service; 

function all() { 
    return $http 
     .get('api/somethings') 
     .then(function(response) { 
      somethings = parseSomethings(response.data); 
      return somethings; 
     }); 
} 

// Some Controller in Angular 1 
var vm = this; 
vm.somethings = []; 
vm.loading = true; 

loadThings(); 

function loadThings() { 
    SomeFactory 
     .all() 
     .then(function(somethings) { 
      vm.somethings = somethings; 
     }) 
     .finally(function() { 
      vm.loading = false; 
     }) 
} 

Jetzt RxJs beobachtbar und Betreff ich mit etwas ähnlichem mit angular2 erreichen kann. Aber ich bin mir nicht sicher, wie ich dem Caller "Completion Hooks" zurückliefern kann. (ZB: Das Laden im angular1 Controller)

Was habe ich versucht, mit für angular2 ist etwas Ähnliches:

// Some Service in Angular 2 
export class SomeService { 
    private _somethings$: Subject<Something[]>; 
    private dataStore: { 
     somethings: Something[] 
    }; 

    constructor(private http: Http) {} 

    get _somethings$() : Observable<Something[]> { 
     return this._somethings$.asObservable(); 
    } 

    loadAll() { 
     this.http 
      .get(`api/somethings`) 
      .map(response => response.json()) 
      .subscribe(
       response => { 
        this.dataStore.somethings = parseSomethings(response.data); 
        this._somethings$.next(this.dataStore.somethings); 
       } 
      ); 
    } 
} 

//Some Component in Angular 2 
export class SomeComponent() { 

    constructor(private someService: SomeService) {} 

    ngOnInit() { 
     this.someService.loadAll(); 
     this.somethings = this.someService.somethings$; 
    } 
} 

Hinweis

verwendete ich ein Thema/beobachtbare hier so, dass wenn ich schaffen/update/remove 'etwas', das ich anrufen kann .next, um die Abonnenten zu benachrichtigen.

ZB:

create(something: Something) : Observable<Something>{ 
    return this.http.post(`api/somethings`, JSON.stringify(something)) 
     .map(response => response.json()) 
     .do(
      something => { 
       this.dataStore.somethings.push(something); 
       this._somethings$.next(this.dataStore.somethings); //Notify the subscribers 
      } 
     ); 
} 

Hinweis

Hier habe ich noch in der Methode .do und wenn das Verfahren in einer 'Form Komponente' Aufruf abonniere ich gerade Abschluss-Handler zu erhalten:

this.someService.create(something).subscribe(
(ok) => ... 
(error) => ... 
() => stop loading indicator 
) 

Fragen

  • Wie können wir einen Completion-Hook an Anrufer übergeben (z.B. Winkel 1 Controller) in Winkel 2 mit RxJs
  • Welche alternativen Pfade gibt es, um ein ähnliches Verhalten zu erreichen?
+1

Hey Im zu bekommen. Aber von meinem Verständnis her wollen Sie wissen, wann die 'get'-Funktion beendet ist, um' loading' auf 'false' zu setzen. In diesem Fall verschieben Sie den Block "subscribe" in Ihrem Dienst zu Ihrer Komponente und setzen Sie dort das Flag "loading". –

+0

Ok, sollte ich mich in der Komponente abmelden (sagen wir nach dem Aufruf von create.subscribe() bei einem Klick auf die Schaltfläche) – RVandersteen

+0

Nein, für 'http.get' und' http.post' werden sie abgeschlossen, sobald die Antwort zurückgegeben wird Sie müssen sie nicht abbestellen. –

Antwort

2

Ihr letztes Codebeispiel ist in Ordnung. Verwenden Sie einfach map() anstelle von subscribe() und abonnieren Sie auf der Aufrufseite. nicht ganz vertraut mit AngularJS

können Sie verwenden

return http.post(...).toPromise(val => ...)) 

oder

return http.post(...).map(...).toPromise(val => ...)) 

das gleiche Verhalten wie in Angular, wo man mit Kette nachfolgende Aufrufe .then(...)

+0

Ich dachte über die Verwendung von Map aswel nach. Wäre es für dich auch ok? – RVandersteen

+0

Der von 'map()' zurückgegebene Wert wird an den Abonnenten weitergeleitet. Wenn Sie den Wert nicht ändern wollen, sondern nur für jedes Ereignis einige Nebeneffekte haben wollen, dann ist auch 'do()' in Ordnung. –

+0

Kann ich davon ausgehen, dass mehrere .map-Aufrufe einfach "kaskadieren", wie es wäre? – RVandersteen