Angular 4 Данные в службе, переходящие к компонентам

Имею некоторые данные в службе и отлично работал, когда у меня были данные в объекте, находящемся в службе, но теперь, когда я подключил соединение с базой данных, данные никогда не попадают в компонент.

Я хочу, чтобы служба подписывалась на данные, возвращаемые из базы данных, и определяла вызов следующим образом:

  public setPerson(ac: string): void{
    console.log(ac);
    this.generatePerson(ac).subscribe((data) => {
        // this.mapPersonFromInput(data[0]);
        console.dir(data);
    });

  }

Функция mapPersonFrominput() является пережитком фиктивных данных. по существу это то же самое, что и extractData ниже, но из статического объекта в коде.

generatePerson выглядит следующим образом:

public generatePerson(id: string):Observable<Person>{
    var datRetUrl: string = '/api/'
    var fullUrl: string = datRetUrl + id;
    return this.http.get(fullUrl)
                .map(this.extractData)
                .catch(this.handleError);
  }

ExtractData просто присваивает значения из входного объекта структуре объекта службы, а handleerror просто записывает ошибку в консоль.

Я вызываю службу для инициализации объекта данных из компонента перед загрузкой компонента, вызывая эту функцию из компонента навигации:

  passCodeToService():void{
    this.psn.setPerson(this.accessCode);
    this.route.navigate(['/name']);
  }

и в фактическом компоненте, который должен получить данные, я использую ngOnInit, но я думаю, что я должен использовать ngOnChanges для инициализации компонента. Вот код, который я сейчас использую, но пока не удалось исправить.

ngOnInit() {
  this.name =this.psn.getName();
  console.log(this.name);
}

getName() просто возвращает объект, который я храню в сервисе.

  public getName(): Name{
    return this.servicePerson.name;
  }

person Chris Rutherford    schedule 02.08.2017    source источник
comment
Пара моментов: во-первых, что делает this.mapPersonFromInput(data[0]);? Во-вторых, где this.psn.getName(); из вашего примера в методе инициализации?   -  person JSess    schedule 02.08.2017
comment
обновлено запрошенной информацией   -  person Chris Rutherford    schedule 02.08.2017
comment
Где вы звоните .subscribe() на generatePerson() и видели ли вы общение через тему   -  person 0mpurdy    schedule 02.08.2017
comment
это было именно так, как я делал это раньше, но это было основано на взаимном взаимодействии между компонентом и сервисом. и да! Я только что нашел эту статью. Похоже, это хорошее начало!   -  person Chris Rutherford    schedule 02.08.2017


Ответы (1)


Вы не должны использовать ngOnChanges здесь, это не предназначено для того, что вы пытаетесь сделать.

Согласно вашему вопросу, это то, чего вы пытаетесь достичь:

  • Получить данные из БД
  • Ваш компонент должен иметь возможность асинхронно получать часть этих данных.

Вы можете добиться этого с помощью кода, который у вас есть. Все, что вам нужно сделать, это добавить еще немного кода и использовать RxJS. Более конкретно:

  • Создайте тему человека в личном сервисе
  • Когда данные вернутся из вашей БД, выполните personSubject.next(dataFromDB), чтобы добавить их в поток людей.
  • Создайте функцию, которая будет возвращать субъект человека в качестве наблюдаемого, а затем вы можете подписаться на этот наблюдаемый объект из своего компонента.

При таком подходе каждый раз, когда данные поступают из вашей БД, эти данные будут добавляться в поток людей, и все, кто подпишется на этот поток (ваш компонент), получит данные.

Быстрый пример (поскольку у меня нет вашего полного кода):

import { ReplaySubject } from 'rxjs/ReplaySubject';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class PersonService {
    // The person subject
    personStream: ReplaySubject<Person> = new ReplaySubject();

    // The person observable
    person$(): Observable<Person> {
        return this.personStream.asObservable();
    }

    // Get person from DB and add to stream
    getDataFromDB() {
        this.http.get(url).subscribe(response => {
            this.personStream.next(response.person);
        });
    }
}

@Component({...})
export class MyComponent implements OnInit {
    person: Person;

    constructor(private personService: PersonService) {}

    ngOnInit() {
        // Subscribe to person observable. Any time person data changes, this will be called.
        this.personService.person$().subscribe(person => this.person = person);

        // If you return the `this.http.get(url)` from `getDataFromDB`, you can just do this instead...
        this.personService.getDataFromDB().subscribe(person => this.person = person);
    }
}

Но это все излишество, потому что на самом деле все, что вам нужно сделать, это подписаться на функцию getDataFromDB в вашем компоненте, поскольку она сама может возвращать наблюдаемое типа Person.

person Lansana Camara    schedule 02.08.2017
comment
Я собираюсь реализовать это и протестировать. Спасибо @lasana - person Chris Rutherford; 02.08.2017
comment
Да, но мне нравится идея, и есть пять подкомпонентов, которым нужны данные из службы, так что это может быть не излишним, проблема в том виде, в каком она представлена, упрощена по сравнению с реальным проектом. - person Chris Rutherford; 02.08.2017
comment
Я вижу, это хороший момент. Ну, я просто пытался сделать это как можно проще :P Но да, это обычно хорошая практика для наблюдаемых потоков. - person Lansana Camara; 02.08.2017
comment
какой импорт следует использовать с этим? ReplaySubject From ?? все остальное выглядит стандартно - person Chris Rutherford; 02.08.2017
comment
Обновил мой ответ импортом для службы. - person Lansana Camara; 02.08.2017
comment
отлично! Благодарность! внедряем сейчас! Хотел бы я дать вам +1 или что-то в этом роде - person Chris Rutherford; 02.08.2017
comment
Без проблем! Убедитесь, что вы НЕ делаете import { ... } from 'rxjs', потому что это включает в себя всю библиотеку rxjs, и если вы сделаете это в нескольких местах, размер вашей сборки будет увеличиваться параллельно. Кроме того, вы можете проголосовать или принять ответ, если он вам подходит. - person Lansana Camara; 02.08.2017
comment
Давайте продолжим обсуждение в чате. - person Chris Rutherford; 02.08.2017