2016-05-31 4 views
2

Я нашел пример из angular.io. Этот пример очень похож на мое приложение с такими же методами. В этом примере используется Promises, но я использую Observables. Если я использую этот пример в качестве ссылки, у меня есть каждый метод, работающий в моем приложении, за исключением метода getHero в службе и ngOnInit в HeroDetailComponent. Поэтому мне интересно, может ли кто-нибудь помочь и преобразовать этот метод в наблюдаемый, потому что у меня возникают проблемы с синтаксисом. Вот коды мне нужно, преобразованные в Observable и plunkerHTTP: Angular 2 + TS Как использовать Observables в HTTP

//HeroService 
    getHero(id: number) { // my id is String 
    return this.getHeroes() 
       .then(heroes => heroes.filter(hero => hero.id === id)[0]); 
    } 


//HeroDetailComponent 
    ngOnInit() { 
    if (this.routeParams.get('id') !== null) { 
     let id = +this.routeParams.get('id'); 
     this.navigated = true; 
     this.heroService.getHero(id) 
      .then(hero => this.hero = hero); 
    } else { 
     this.navigated = false; 
     this.hero = new Hero(); 
    } 
    } 

Так что я хочу что-то вроде этого:

//HeroService 
public getHero(id: string) {  
    return this.getHeroes() 
    .subscribe(heroes => this.heroes.filter(hero => heroes.id === id)[0]); //BTW, what does this [0] mean??   
} 

EDIT: Я был на самом деле получить список непосредственно, он не работал с return this.heroes, как это предложено в ответах ниже. Рабочий пример:

public getById(id: string) { 
    //return this.getHeroes() <---- didn't work 
    return this.http.get('someUrl') // WORKS! 
    .map(heroes => this.heroes.filter(hero => hero.id === id)[0]);   
} 

Теперь у меня все еще возникают проблемы с моим ngOnit, и я не могу понять почему!

ngOnInit(){ 
    let id = this._routeParams.get('id'); 
    this.heroService.getById(id) 
    //console.log("retrieved id: ",id) <----- gives correct id! 
    .subscribe(hero => this.hero = hero); 
    //console.log("hero: ", this.hero); <----- gives undefined! 
} 

EDIT2, по-прежнему получать неопределенными при попытке перейти на страницу подробно :(Я думаю, что у вас один кронштейн много в своем ответе, попытался посмотреть и получить правильные места для скобок?

ngOnInit(){ 
    let id = this._routeParams.get('id'); 
    this.heroService.getById(id) 
    .subscribe(heroes => { 
     // this code is executed when the response from the server arrives 
     this.hero = hero 
    }); 
    // code here is executed before code from the server arrives 
    // even though it is written below 
} 

ответ

2

Если вы звоните subscribe() на ObservableSubscription возвращается. вы не можете позвонить subscribe() по подписке.

Вместо этого используйте только оператор (map()) и использовать subscribe() на месте вызова:

public getHero(id: string) {  
    return this.getHeroes() 
    .map(heroes => this.heroes.filter(hero => heroes.id === id)[0]); 
} 

ngOnInit(){ 
    let id = this._routeParams.get('id'); 
    this.heroService.getHero(id) 
    .subscribe(hero => this.hero = hero); 
} 

В отличие от subscribe(), map() также работает на Observable, но и возвращает Observable.

[0] означает просто взять первый элемент отфильтрованных героев.

обновление

ngOnInit(){ 
    let id = this._routeParams.get('id'); 
    this._searchService.getById(id) 
    .subscribe(searchCase => { 
     // this code is executed when the response from the server arrives 
     this.searchCase = searchCase; 
     console.log("id: ", this.searchCase); 
    }); 
    // code here is executed before code from the server arrives 
    // event though it is written below 
} 

Этот код является функцией

searchCase => { 
     // this code is executed when the response from the server arrives 
     this.searchCase = searchCase); 
     console.log("id: ", this.searchCase); 
    } 

, который передается subscribe() и Observable вызывает эту функцию, когда она имеет новые данные для абонента. Поэтому этот код не выполняется немедленно, но только тогда, когда наблюдаемый испускает новые данные.

Код, который приходит после subscribe(), выполняется немедленно и поэтому перед функцией выше, и поэтому this.searchCase еще не имеет значения.

+0

СПАСИБО! GetHero работает как шарм, но теперь у меня есть ошибка (wierd?) В моем ngOnInit. Вы можете помочь? Обновлен мой вопрос! – Alex

+0

Я обновил свой ответ. –

+0

Очень хорошее объяснение, спасибо! Я новичок в кодировании в целом, и я помню, что я натолкнулся на это где-то, где это одно из различий между обещаниями и наблюдаемыми. Но, наверное, я забыл об этом! Обновленный вопрос снова, потому что страница детали, к которой я перехожу, по-прежнему жалуется на то, что она не определена! Наверное, у вас слишком много одной скобки или слишком мало, я попытался поместить скобки в правильные места, но я думаю, что это все еще неправильно? – Alex

1

Это, как вы можете это сделать:

//HeroService 
public getHero(id: string) {  
    return this.getHeroes() 
     .map(heroes => this.heroes.filter(hero => heroes.id === id)[0]); 
} 

//HeroDetailComponent 
ngOnInit(){ 
    let id = this._routeParams.get('id'); 
    this.heroService.getHero(id) 
     .subscribe(hero => { 
      // your code here 
     }); 
} 

[0] является сбруя массив. Вы выбираете первый элемент в индексе массива 0 с ним.Вам это нужно, потому что Array.filter() возвращает новый массив с отфильтрованными значениями, но вам нужен только один герой.

-1

хорошие ответы здесь, но пришлось настроить их немного, так что я добавляю мое собственное

служба выглядит так ...

import {Injectable}  from '@angular/core'; 
import {Http, Response} from '@angular/http'; 
import {Person} from '../models/person'; 
import {Observable} from 'rxjs/Observable'; 
import 'rxjs/add/operator/catch'; 

@Injectable() 
export class PersonService { 
    private personsUrl = 'app/data/persons.json'; 

    constructor(private http:Http) { 
    } 

    getPersons():Observable<Person[]> { 
    return this.http.get(this.personsUrl) 
     .map(
     (res:Response) => { 
      let persons = res.json(); 
      return persons || {}; 
     } 
    ) 
     .catch(this.handleError); 
    } 

    getPerson(id:number) { 
    return this.getPersons() 
     .map(persons => persons.filter(person => person.id === id)[0]); 
    } 

    private handleError(error:any) { 
    let errMsg = (error.message) ? error.message : 
     error.status ? `${error.status} - ${error.statusText}` : 'Server error'; 
    console.error(errMsg); 
    return Observable.throw(errMsg); 
    } 
} 
+0

В чем принципиальная разница? –

+0

.map (persons => persons.filter (person => person.id === id) [0]); – danday74

+0

Это не похоже на вопрос. Эта строка фильтра уже находится в вопросе, и вы просто переименовали 'Hero' в' Person'. Какова цель этого ответа? –

Смежные вопросы