2016-01-12 11 views
9

Mam prawdziwy problem owijając głowę wokół obserwowalnych i subskrypcji w kanale2. Problem, który obecnie mam, jest następujący:Mam funkcję wykonywania komponentu po zakończeniu usługi http.get call

Mam usługę, która zawiera metody publikowania i pobierania danych z interfejsu API. Usługa jest wstrzykiwana do komponentu, który bezpośrednio wywołuje te metody w usłudze. Usługa pobiera dane i przechowuje je samodzielnie, ale chcę przetworzyć te dane w komponencie. Nie mogę się dowiedzieć, jak sprawić, by komponent wykonywał funkcję po tym, jak usługa odzyskała i zapisała dane.

service.ts

import { Injectable } from 'angular2/core';  
import { Http } from 'angular2/router'; 

@Injectable() 
export class Service { 
    result: Object; 

    constructor(http: Http) { 
     this.http = http; 
    } 

    httpGet(url) { 
     return this.http.get(url).subscribe(
      result => this.result = result.json(), 
      error => console.log(error), 
      () => {} 
     ) 
    } 
} 

component.ts

import { Component } from 'angular2/core'; 
import { Service } from './service'; 

@Component({ 
    ... 
}) 
export class Component { 
    formattedResult: Object; 

    constructor(service: Service) { 
     this.service = service; 
     this.service.httpGet('/api') 

     // How do I call format result on service.result only after it is completed? 
     this.formatResult(service.result) // Need to execute this after the http call is completed 

     // I want something like: 
     this.service.httpGet('/api').then(() => formatResult(this.service.result)); 
    } 

    formatResult(result) { 
     this.formattedResult = result.map(x => x.length) // For example 
    } 
} 
+1

http://stackoverflow.com/questions/34739574/notification-component-when-service-function-is-complete-in-angular/34739630#34739630 –

+0

@ GünterZöchbauer Dzięki, jest blisko, ale chciałem zachować. subskrybuj w usłudze, ponieważ przechowuje ona te informacje w celu późniejszego dostępu. Nie można mieć dwóch .subscribes na jednym http.get (będzie on wywoływał dwa razy). Chyba, że ​​zaakceptowany wzór projektu ma mieć subskrypcję tylko w komponentach i jawnie ustawić zmienne usługi ze składnika? Chciałem zachować oddzielną logikę usług i komponentów. –

+0

http://stackoverflow.com/a/34405243/215945 - ta odpowiedź wyświetla obserwowalne łańcuchy za pomocą 'flatMap()'. –

Odpowiedz

2

Sprawdź, czy wynik już przybył, a jeżeli tak, należy utworzyć nową obietnicę i wypełnić go z wyniku, nie nie, pobierz i zwróć to również jako obietnicę.

@Injectable() 
export class Service { 
    result: Object; 

    constructor(http: Http) { 
     this.http = http; 
    } 

    httpGet(url) { 
     if(result === undefined) { 
      return this.http.get(url).toPromise().then(
       result => this.result = result.json(), 
       error => console.log(error); 
     ); 
     } else { 
      return new Promise().resolve(result); 
     } 
    } 
} 

Nie wiem, TS i ten kod może zawierać pewne błędy (używam tylko Kątowy Dart), ale powinieneś dostać pomysł.

Zobacz także
- http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html

+0

Dobra, rozumiem, jak to działa. Wydaje się trochę wstydu, po prostu przekształcić go z powrotem w obietnice, dzięki czemu można .then chain. Miałem nadzieję, że pojawił się nowy, możliwy do zaobserwowania sposób, o którym po prostu nie wiedziałem. No cóż - dziękuję! –

+0

Jak już wspomniałem, nie jestem programistą TS, ale z innych postów, które widziałem, wygląda na to, że mam iść. –

3

Aby odpowiedzieć na moje własne pytanie:

w katalogu aplikacji, Rxjs importu z:

import 'rxjs/Rx'; 

Daje to dostęp do pełnej obserwowalnych obiektu (nie tylko "Observable-lite" dołączone do Angular). Pozwala to na .map .reduce itp. Żądań HTTP.

Możesz teraz użyć .map na żądanie HTTP, aby wykonać dowolny kod w kontekście usługi, nawet jeśli jest to składnik, który subskrybuje wynik. Tak, aby osiągnąć to, co określone zrobić na początku, możemy:

service.ts

import { Injectable } from 'angular2/core';  
import { Http } from 'angular2/router'; 

@Injectable() 
export class Service { 
    result: Object; 

    constructor(http: Http) { 
     this.http = http; 
    } 

    httpGet(url) { 
     return this.http.get(url).map(
      result => { 
       let data = result.json(); 
       this.result = data; 
       return data 
      } 
     ) 
    } 
} 

component.ts

import { Component } from 'angular2/core'; 
import { Service } from './service'; 

@Component({ 
    // Component setup 
}) 
export class Component { 
    formattedResult: Object; 

    constructor(service: Service) { 
     this.service = service; 
     this.service.httpGet('/api').subscribe(
      data => this.formatResult(data); 
     ); 
    } 

    formatResult(result) { 
     this.formattedResult = result.map(x => x.length) // For example 
    } 
} 

Dzięki Gunter i Mark za odpowiedzi, pomógł opowiadam sobie o tym trochę i czuję, że rozumiem Observables znacznie lepiej, gdy przeszedłem przez wiele dokumentów rozwiązujących ten problem!

+0

Aby włączyć operatorów z rxjs, utwórz plik rxjs-extensions.ts i umieść go w swoich polyfilach, dodaj import dla używanych operatorów jako import "rxjs/operator/map" itd. Nigdy nie importuj pełnej biblioteki jako import 'rxjs/Rx', ponieważ nie jest potrzebne. Możesz sprawdzić, co jest zawarte w twoich mapach za pomocą różnych odkrywców map źródłowych dla pakietu internetowego, kątowego, js –

0

Cóż można użyć połączenia z powrotem funkcji w takim przypadku

Biorąc przykład rozważenia jest to funkcja po którym uruchamia usługi pocztowe w module serwisowym

postData(id: string, name: string) { 
    console.log("Got you",id); 
    this._employeeService.postServices({id: id, name: name}) 
    .subscribe(
     (response:Response) => this.consoleMyOutput(), 
     error => console.log(error) 
    ); 
} 

Tutaj należy zwrócić uwagę na funkcję consoleMyOutput(). ten zostanie uruchomiony, gdy odpowiedź dostał po usługa została nazwana

Teraz

consoleMyOutput(){console.log("Write Your call back function")}; 

Ta funkcja zostanie uruchomiona zaraz po tym.

Powiązane problemy