如何在共享 class 和 angular 2 组件之间传输数据?
How do I transfer data between a shared class and an angular 2 component?
我正在使用独立的 TypeScript class 调用我的后端服务。在实例化我的共享 class 实例时,我能够 console.log
捕获数据。但是,我无法访问 angular 组件中 class 的本地属性和方法。
这是我的组件:
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;
}
}
这是我共享的 class 模块:
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;
}
}
如您所见,
我想使用 this.service.getAllProjects()
在我的 ng 组件中填充我的局部变量 projects
。当我尝试记录来自共享 class ProjectService
的响应时,函数响应是 undefined
.
当我在 ProjectService
构造函数中 console.log
使用 new
初始化 class 后,我可以看到我的 class 能够捕获响应.
为什么要这样做?另外,我该如何解决?
谢谢大家。
您在实例化 ProjectService 对象时没有等待响应完成。项目 属性 尚未设置。我建议您对项目 属性 使用 behaviorSubject。您可以阅读有关 subjects 和 behaviorSubject here 的内容。
正如 user1986938 所指出的,您的问题是您的 API 调用是异步的,您必须等待 API 响应才能对您的数据执行某些操作。
在 Angular
中,您可以轻松地依靠 RxJs 与 Angular
紧密耦合的库来做到这一点。
这是一个working example,您可以轻松地适应您的情况。
您可以看到,在这个示例中我使用了 ReplaySubject
,因为它能够再次为任何新订阅者提供价值,即使在您的 API 通话结束后也是如此。
具体来说,这允许您从您的 ProjectService
中多次查询所有项目的列表,并且可能从您应用程序的不同部分查询,而不必多次执行真正的 API 调用,也不必关心其他任何事情。
如果您不熟悉 ReactiveX
概念,我建议您阅读这篇关于 Subjects
.
的精彩 documentation, and for your case, this part
组件
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));
}
}
好的,所以对我有用的是在 http 请求完成时使用 EventEmitter 发出项目,如 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);
});
}
}
我正在使用独立的 TypeScript class 调用我的后端服务。在实例化我的共享 class 实例时,我能够 console.log
捕获数据。但是,我无法访问 angular 组件中 class 的本地属性和方法。
这是我的组件:
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;
}
}
这是我共享的 class 模块:
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;
}
}
如您所见,
我想使用 this.service.getAllProjects()
在我的 ng 组件中填充我的局部变量 projects
。当我尝试记录来自共享 class ProjectService
的响应时,函数响应是 undefined
.
当我在 ProjectService
构造函数中 console.log
使用 new
初始化 class 后,我可以看到我的 class 能够捕获响应.
为什么要这样做?另外,我该如何解决?
谢谢大家。
您在实例化 ProjectService 对象时没有等待响应完成。项目 属性 尚未设置。我建议您对项目 属性 使用 behaviorSubject。您可以阅读有关 subjects 和 behaviorSubject here 的内容。
正如 user1986938 所指出的,您的问题是您的 API 调用是异步的,您必须等待 API 响应才能对您的数据执行某些操作。
在 Angular
中,您可以轻松地依靠 RxJs 与 Angular
紧密耦合的库来做到这一点。
这是一个working example,您可以轻松地适应您的情况。
您可以看到,在这个示例中我使用了 ReplaySubject
,因为它能够再次为任何新订阅者提供价值,即使在您的 API 通话结束后也是如此。
具体来说,这允许您从您的 ProjectService
中多次查询所有项目的列表,并且可能从您应用程序的不同部分查询,而不必多次执行真正的 API 调用,也不必关心其他任何事情。
如果您不熟悉 ReactiveX
概念,我建议您阅读这篇关于 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));
}
}
好的,所以对我有用的是在 http 请求完成时使用 EventEmitter 发出项目,如 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);
});
}
}