Angular 6: 在调用 HTTP 请求后未设置 class 的属性
Angular 6: not set properties of class after calling HTTP-request
我有带标签的组件(ProfileComponent
是其他组件的父组件)。我想使用 ProjekteingangComponent
中的服务(角色和项目)从服务器加载数据。
我为此函数编写了加载数据(loadRoles()
和 loadProjects()
)并在 ngOnInit()
上调用它,但问题是 value
没有设置 this.roles
和 this.projects
。 Here and here 在浏览器中输出到控制台。
正如您在 loadRoles()
和 loadProjects()
中的输出 value
中看到的那样,在错误之后写入。我该如何改进并正确设置 ngOnInit()
中的 this.projects
和 this.roles
?
projekteingang.component.ts:
import {Component, Input, OnInit} from '@angular/core';
import {ProfileComponent} from '../profile.component';
import {UserOfferMapping} from "../../../_models/UserOfferMapping";
import {UseroffermappingService} from "../../../_services/useroffermapping.service";
import {Userproject} from "../../../_models/Userproject";
import {Userrole} from "../../../_models/userrole";
import {UserprojectService} from "../../../_services/userproject.service";
import {UserroleService} from "../../../_services/userrole.service";
import {ProjectUtils} from "../../../utils/ProjectUtils";
@Component({
selector: 'app-projekteingang',
templateUrl: './projekteingang.component.html',
styleUrls: ['./projekteingang.component.css']
})
export class ProjekteingangComponent implements OnInit {
public userOfferMapping: any[];
public userId: number;
public offerDataSource: any[] = [];
public projects: Userproject[] = [];
public roles: Userrole[] = [];
constructor(
private profileComponent: ProfileComponent,
private useroffremappingService: UseroffermappingService,
private userProjectService: UserprojectService,
private userRoleService: UserroleService,) {
}
loadRoles() {
this.userRoleService.getAllRoles().toPromise().then((value) => {
console.log("value roles");
console.log(value);
this.roles = value;
});
}
loadProjects(){
this.userProjectService.getAllProjects().toPromise().then((value) => {
console.log("value projects");
console.log(value);
this.projects = value;
});
}
ngOnInit() {
this.userId = this.profileComponent.currentUser.id;
this.loadProjects();
this.loadRoles();
console.log("roles ngoinit");
console.log(this.roles);
console.log("projects ngoinit");
console.log(this.projects);
this.loadUserOfferMappings();
}
findProjectByID(id) {
let project = null;
this.projects.map(elem => {
if (elem.id == id) {
project = elem;
}
})
return project;
}
findRoleByID(id) {
let role = null;
this.roles.map(elem => {
if (elem.id == id) {
role = elem;
}
})
return role;
}
loadUserOfferMappings() {
console.log("roles in func");
console.log(this.roles);
console.log("projects in func");
console.log(this.projects);
this.useroffremappingService.getAllUseroffermappingsByUserId(this.userId).subscribe(value => {
console.log("Useroffermapping");
console.log(value);
this.userOfferMapping = value;
value.map(elem => {
console.log(elem);
let project = this.findProjectByID(elem.projectId);
let role = this.findRoleByID(elem.roleId);
console.log(role);
console.log(project);
this.offerDataSource.push({
projectId: elem.projectId,
roleId: elem.roleId,
projectName: project.name,
roleName: role.name,
roleTooltip: role.description
});
})
});
}
get profile() {
return this.profileComponent;
}
}
profile.component.html:
<mat-tab-group>
<-- ... -->
<-- another tabs -->
<-- ... -->
<mat-tab label="Projekt eingang">
<app-projekteingang></app-projekteingang>
</mat-tab>
</mat-tab-group>
我看到很多被误解的事情:
- 不需要使用
.toPromise()
改用.subscribe(...)
:
loadProjects(){
this.userProjectService.getAllProjects().subscribe((value) => {
console.log("value projects");
console.log(value);
this.projects = value;
});
}
- 您正在获取异步数据
您必须等待它们才能使用它们。
- 您的关键代码需要所有 3 个调用的答案
所以你必须将这段代码提取到另一个方法,在每次数据接收时调用(检查你是否有所有数据)
loadRoles() {
this.userRoleService.getAllRoles().subscribe((value) => {
console.log("value roles");
console.log(value);
this.roles = value;
this.feedOfferDataSource();
});
}
loadProjects(){
this.userProjectService.getAllProjects().subscribe((value) => {
console.log("value projects");
console.log(value);
this.projects = value;
this.feedOfferDataSource();
});
}
loadUserOfferMappings() {
console.log("roles in func");
console.log(this.roles);
console.log("projects in func");
console.log(this.projects);
this.useroffremappingService.getAllUseroffermappingsByUserId(this.userId).subscribe(value => {
console.log("Useroffermapping");
console.log(value);
this.userOfferMapping = value;
this.feedOfferDataSource();
}
}
feedOfferDataSource() {
if(!this.projects || !this.roles || !this.userOfferMapping) return;
this.offerDataSource = this.userOfferMapping.map(elem => {
console.log(elem);
let project = this.findProjectByID(elem.projectId);
let role = this.findRoleByID(elem.roleId);
console.log(role);
console.log(project);
return {
projectId: elem.projectId,
roleId: elem.roleId,
projectName: project.name,
roleName: role.name,
roleTooltip: role.description
};
}
- 您使用了
map
而没有使用它的值
getAllRoles
、getAllProjects
和 getAllUseroffermappingsByUserId
是三个独立的异步调用。一个不能保证三个完成的先后顺序
现在函数 loadUserOfferMappings
实际上取决于为角色和项目获取的数据。因此,这意味着 getAllUseroffermappingsByUserId
应仅在项目和角色已获取后调用。
现在有多种方法可以解决这个问题:
最新手的方法是在使用getAllUseroffermappingsByUserId
;
之前检查角色和项目是否可用
更明智的方法是在仅解析角色和项目调用后实际调用 loadUserOfferMappings
方法。(使用可观察对象或承诺任何内容)
另一种方法是为您的 promise 调用保持加载状态。
例如异步调用处于加载、加载或错误状态。因此,仅当 getRoles
和 getProjects
处于加载状态时才调用 getAllUseroffermappingsByUserId
。
我有带标签的组件(ProfileComponent
是其他组件的父组件)。我想使用 ProjekteingangComponent
中的服务(角色和项目)从服务器加载数据。
我为此函数编写了加载数据(loadRoles()
和 loadProjects()
)并在 ngOnInit()
上调用它,但问题是 value
没有设置 this.roles
和 this.projects
。 Here and here 在浏览器中输出到控制台。
正如您在 loadRoles()
和 loadProjects()
中的输出 value
中看到的那样,在错误之后写入。我该如何改进并正确设置 ngOnInit()
中的 this.projects
和 this.roles
?
projekteingang.component.ts:
import {Component, Input, OnInit} from '@angular/core';
import {ProfileComponent} from '../profile.component';
import {UserOfferMapping} from "../../../_models/UserOfferMapping";
import {UseroffermappingService} from "../../../_services/useroffermapping.service";
import {Userproject} from "../../../_models/Userproject";
import {Userrole} from "../../../_models/userrole";
import {UserprojectService} from "../../../_services/userproject.service";
import {UserroleService} from "../../../_services/userrole.service";
import {ProjectUtils} from "../../../utils/ProjectUtils";
@Component({
selector: 'app-projekteingang',
templateUrl: './projekteingang.component.html',
styleUrls: ['./projekteingang.component.css']
})
export class ProjekteingangComponent implements OnInit {
public userOfferMapping: any[];
public userId: number;
public offerDataSource: any[] = [];
public projects: Userproject[] = [];
public roles: Userrole[] = [];
constructor(
private profileComponent: ProfileComponent,
private useroffremappingService: UseroffermappingService,
private userProjectService: UserprojectService,
private userRoleService: UserroleService,) {
}
loadRoles() {
this.userRoleService.getAllRoles().toPromise().then((value) => {
console.log("value roles");
console.log(value);
this.roles = value;
});
}
loadProjects(){
this.userProjectService.getAllProjects().toPromise().then((value) => {
console.log("value projects");
console.log(value);
this.projects = value;
});
}
ngOnInit() {
this.userId = this.profileComponent.currentUser.id;
this.loadProjects();
this.loadRoles();
console.log("roles ngoinit");
console.log(this.roles);
console.log("projects ngoinit");
console.log(this.projects);
this.loadUserOfferMappings();
}
findProjectByID(id) {
let project = null;
this.projects.map(elem => {
if (elem.id == id) {
project = elem;
}
})
return project;
}
findRoleByID(id) {
let role = null;
this.roles.map(elem => {
if (elem.id == id) {
role = elem;
}
})
return role;
}
loadUserOfferMappings() {
console.log("roles in func");
console.log(this.roles);
console.log("projects in func");
console.log(this.projects);
this.useroffremappingService.getAllUseroffermappingsByUserId(this.userId).subscribe(value => {
console.log("Useroffermapping");
console.log(value);
this.userOfferMapping = value;
value.map(elem => {
console.log(elem);
let project = this.findProjectByID(elem.projectId);
let role = this.findRoleByID(elem.roleId);
console.log(role);
console.log(project);
this.offerDataSource.push({
projectId: elem.projectId,
roleId: elem.roleId,
projectName: project.name,
roleName: role.name,
roleTooltip: role.description
});
})
});
}
get profile() {
return this.profileComponent;
}
}
profile.component.html:
<mat-tab-group>
<-- ... -->
<-- another tabs -->
<-- ... -->
<mat-tab label="Projekt eingang">
<app-projekteingang></app-projekteingang>
</mat-tab>
</mat-tab-group>
我看到很多被误解的事情:
- 不需要使用
.toPromise()
改用.subscribe(...)
:
loadProjects(){
this.userProjectService.getAllProjects().subscribe((value) => {
console.log("value projects");
console.log(value);
this.projects = value;
});
}
- 您正在获取异步数据
您必须等待它们才能使用它们。
- 您的关键代码需要所有 3 个调用的答案
所以你必须将这段代码提取到另一个方法,在每次数据接收时调用(检查你是否有所有数据)
loadRoles() {
this.userRoleService.getAllRoles().subscribe((value) => {
console.log("value roles");
console.log(value);
this.roles = value;
this.feedOfferDataSource();
});
}
loadProjects(){
this.userProjectService.getAllProjects().subscribe((value) => {
console.log("value projects");
console.log(value);
this.projects = value;
this.feedOfferDataSource();
});
}
loadUserOfferMappings() {
console.log("roles in func");
console.log(this.roles);
console.log("projects in func");
console.log(this.projects);
this.useroffremappingService.getAllUseroffermappingsByUserId(this.userId).subscribe(value => {
console.log("Useroffermapping");
console.log(value);
this.userOfferMapping = value;
this.feedOfferDataSource();
}
}
feedOfferDataSource() {
if(!this.projects || !this.roles || !this.userOfferMapping) return;
this.offerDataSource = this.userOfferMapping.map(elem => {
console.log(elem);
let project = this.findProjectByID(elem.projectId);
let role = this.findRoleByID(elem.roleId);
console.log(role);
console.log(project);
return {
projectId: elem.projectId,
roleId: elem.roleId,
projectName: project.name,
roleName: role.name,
roleTooltip: role.description
};
}
- 您使用了
map
而没有使用它的值
getAllRoles
、getAllProjects
和 getAllUseroffermappingsByUserId
是三个独立的异步调用。一个不能保证三个完成的先后顺序
现在函数 loadUserOfferMappings
实际上取决于为角色和项目获取的数据。因此,这意味着 getAllUseroffermappingsByUserId
应仅在项目和角色已获取后调用。
现在有多种方法可以解决这个问题:
最新手的方法是在使用
getAllUseroffermappingsByUserId
; 之前检查角色和项目是否可用
更明智的方法是在仅解析角色和项目调用后实际调用
loadUserOfferMappings
方法。(使用可观察对象或承诺任何内容)另一种方法是为您的 promise 调用保持加载状态。 例如异步调用处于加载、加载或错误状态。因此,仅当
getRoles
和getProjects
处于加载状态时才调用getAllUseroffermappingsByUserId
。