Как передать данные между общим классом и угловым компонентом? - PullRequest
0 голосов
/ 27 сентября 2018

Я делаю вызовы в свой внутренний сервис, используя независимый класс TypeScript.Я могу console.log захваченные данные при создании экземпляра моего общего класса.Однако у меня возникают проблемы с доступом к локальным свойствам и методам этого класса внутри моего углового компонента.

Вот мой компонент:

import { Component, OnInit } from '@angular/core';
import { ProjectService } from '../shared/projectService';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-about',
  templateUrl: './about.component.html',
  styleUrls: ['./about.component.css']
})

export class AboutComponent implements OnInit {

  projects: any;
  windowWidth: number;
  service: ProjectService;

  constructor(private httpClient: HttpClient) { 
    this.service = new ProjectService(this.httpClient);
    //  returns as undefined
    console.log(this.service.getAllProjects());   
  }

  ngOnInit() {
    this.windowWidth = window.innerWidth;
  }

}

Вот мой модуль общего класса:

import { HttpClient } from '@angular/common/http';

interface Project {
    demoURL: string,
    githubURL: string,
    imgFileName: string,
    name: string,
    stack: Array<string>
}

export class ProjectService {

    private configURL = `https://someURL.herokuapp.com/getAllProjects`;
    projects: any;
    constructor(private httpClient: HttpClient) {

        this.httpClient.get(this.configURL).subscribe(resp => {
            this.projects = resp;
        });
    }

    getAllProjects() {
        return this.projects;
    }
}

Как видите,

Я хочу заполнить свою локальную переменную projects внутри моего компонента ng, используя this.service.getAllProjects().Когда я пытаюсь записать ответ от моего общего класса ProjectService, ответ функции - undefined.

Когда я console.log внутри ProjectService конструктора после того, как я инициализирую класс с помощью new, я вижучто мой класс смог захватить ответ.

Почему он это делает?Кроме того, как я могу это исправить?

Спасибо, ребята.

Ответы [ 3 ]

0 голосов
/ 27 сентября 2018

Как указывает user1986938, ваша проблема в том, что ваш вызов API является асинхронным, и вы должны ждать, пока ответ API сможет что-то сделать с вашими данными.
В Angular вы можете легко сделать это, полагаясь нав RxJs библиотеке, с которой Angular тесно связана.

Вот рабочий пример , который вы можете легко адаптировать к вашему делу.

Вы можете видеть, что в этом примере я использую ReplaySubject, потому что он может снова предоставлять значение любому новому подписчику, даже после того, как ваш вызов API завершен.
Конкретно, это позволяет вам запрашивать список всех ваших проектовиз вашего ProjectService несколько раз и, возможно, из разных частей вашего приложения, без необходимости выполнять реальный вызов API более одного раза и без заботы о чем-либо еще.

Если вы не знакомы с ReactiveXконцепции, я предлагаю вам прочитать эту замечательную документацию , а для вашего случая это part , что составляет примерно Subjects.

компонент

export class AppComponent
{
    // this property allows passing projects to your template
    projects: string[];

    // you can directly inject your service into your component constructor
    constructor ( private projectService: ProjectService )
    {
        // here you subscribe to you projects query observable
        this.projectService.getAll().subscribe(projects =>
        {
            // now you can do what you want with your projects
            console.log('projects: ', projects);
            // here, we store projects in component property to display them in template
            this.projects = projects;
        });
    }
}

сервис

export class ProjectService
{
    // this property is used to store your API response
    private projectsSubject: ReplaySubject<any>;

    constructor ()
    {
        // create subject
        this.projectsSubject = new ReplaySubject();

        // do API call
        this.doFakeAPICall().subscribe(projects =>
        {
            // store response as subject value
            this.projectsSubject.next(projects);
        });
    }

    getAll (): Observable<any>
    {
        // return subject as observable
        return this.projectsSubject.asObservable();
    }

    // replace this be your real API call
    private doFakeAPICall (): Observable<any>
    {
        // here we simulate a response delay of one second
        return of([ 'project 1', 'project 2' ]).pipe(delay(1000));
    }
}
0 голосов
/ 29 сентября 2018

Хорошо, так что у меня сработало использование EventEmitter для генерации проектов после завершения http-запроса, как указано user1986938.

Вот что я сделал:

HttpService:

import { HttpClient } from '@angular/common/http';
import { Injectable, EventEmitter } from '@angular/core';
import { Project } from '../shared/project.interface';

@Injectable()
export class ProjectService {

    private configURL = `https://someURL.herokuapp.com/getAllProjects`;
    public httpResponse = new EventEmitter<Project[]>();
    public projects: Project[];

    constructor(private httpClient: HttpClient) {
        this.httpClient.get(this.configURL).subscribe((res: Project[]) => {
            this.projects = res;
            this.httpResponse.emit(this.getProjects());
        });
    }

    getProjects() {
        return this.projects.slice();
    }
}

Компонент:

import { Component, OnInit } from '@angular/core';
import { ProjectService } from '../shared/project.service';
import { Project } from '../shared/project.interface';

@Component({
  selector: 'app-about',
  templateUrl: './about.component.html',
  styleUrls: ['./about.component.css'],
  providers: [ProjectService]
})

export class AboutComponent implements OnInit {

  projects: Project[];
  windowWidth: number;

  constructor(private projectService: ProjectService) { 
  }

  ngOnInit() {
    this.windowWidth = window.innerWidth;

    this.projectService.httpResponse.subscribe(([first, second]: [Project, Project]) => {
        console.log(first);
        console.log(second);
    });
  }

}
0 голосов
/ 27 сентября 2018

Вы не ожидаете завершения ответа при создании экземпляра объекта ProjectService.Свойство Projects пока не установлено.Я бы посоветовал вам использовать пляжное поведение для проектов.Вы можете прочитать о предметах и ​​поведении субъекта здесь .

...