在 Angular 中获取(HTTP-Get)多个 class 个对象
Fetch(HTTP-Get) multiple class objects in Angular
首先,用我的实际代码解释起来有点混乱,所以我试图用一个更小的例子来简化问题。
假设我的项目从服务器中的 2 个不同 table 接收数据,employeeDetails 和 employeeNames。
employeeNames: 这个 table 有三列,employeeNumber, firstName , 和 lastName。顾名思义,这个 table 包含所有员工的列表,包括他们的名字和姓氏以及唯一的员工编号。
employeeDetails: 这个 table 是我从我的网站获取和 httpPost 数据的地方。例如,假设此 table 具有以下字段:
- employee:以员工号为输入
- 资格:让用户输入各种资格作为字符串
- 主管:取主管的员工编号,而不是姓名
- manager:采用经理的员工编号,而不是姓名
虽然后端是这种情况,但前端 employeeDetails 的接口有更多的成员。这就是它变得棘手的地方。
在前端,angular 界面是这样的:
export interface employeeDetails
{
employee: number;
qualifications: string;
supervisor: number;
manager: number;
employeeName: string;
supervisorName: string;
managerName: string;
}
所以,我使用 httpGet 从后端 api 获取数据,一旦我收到两个 table,我就有一个函数来填充 [=44= 中的额外字段]employeeDetails界面。
控制器
[HttpGet("[action]")]
public IActionResult getEmployeeNames()
{
using (var empApp= new EmployeeTable())
{
var empNames = new List<employeeNames>();
empNames = empApp.employeeNames.ToList();
return Json(empNames);
}
}
[HttpGet("[action]")]
public IActionResult employeeDetails()
{
using (var empApp= new EmployeeTable())
{
var empDetails = new List<employeeDetails>();
empDetails = empApp.employeeDetails.ToList();
return Json(empDetails);
}
}
服务
getEmployeeNames(): Observable<employeeNames[]> {
return this.http.get<employeeNames[]>(this.baseUrl + 'api/employeecontroller/getEmployeeNames')
.pipe(catchError(this.handleError('getItems', [])));
}
getEmployeeDetails(): Observable<employeeDetails[]> {
return this.http.get<employeeDetails[]>(this.baseUrl + 'api/employeecontroller/getEmployeeDetails')
.pipe(catchError(this.handleError('getItems', [])));
}
组件
getEmployeeInfo() {
this.employeeService.getEmployeeNames()
.subscribe(data => this.employeeNames = data);
this.employeeService.getEmployeeDetails()
.subscribe(data => this.employeeDetails = data);
fillEmployeeDetails();
}
fillEmployeeDetails() {
this.employeeDetails.forEach(elem => {
let emp = this.employeeNames.find(employee => {
return (employee.employeeNumber === elem.employeeNumber);
});
let sup = this.employeeNames.find(supervisor => {
return (supervisor.employeeNumber === elem.supervisor);
});
let man = this.employeeNames.find(manager=> {
return (manager.employeeNumber === elem.manager);
});
elem.employeeName = emp.firstName + " " + emp.lastName;
elem.supervisorName= sup.firstName + " " + sup.lastName;
elem.managerName= man.firstName + " " + man.lastName;
});
}
所以,当我试图调用这个函数时,它失败了。
原因是该函数甚至在获取整个 employeeNames table 之前就被调用了。如果没有获取 table,.find() 是 return 大量员工编号的空值,因此,我的函数没有 return 预期的结果。
我的问题
我应该使用 async/await 和 .toPromise() 并避免订阅该服务以等待获取数据,还是有更好的方法?
非常感谢任何帮助或想法。谢谢!
您必须订阅可观察对象才能发起 HTTP 请求。
此外,您不能像在代码片段中那样调用 this.fillEmployeeDetails();
,因为请求是异步的,数据需要一些时间才能返回 - 但是,您调用 this.fillEmployeeDetails
的代码行将被执行发出请求后立即。
当数据返回时,subscribe 中的回调函数以请求响应作为参数被调用。您必须在订阅内调用 this.fillEmployeeDetails();
,因为您会在那里接收数据。
但是你怎么知道两个请求是否已经返回,即你可以启动你的 fill...
函数吗?
最佳解决方案是使用 rxJs 运算符,例如 forkJoin,在这种情况下,它的行为类似于 Promise.all()。也就是说,它仅在所有可观察对象(在您的情况下为请求)都已完成执行时触发其在订阅内的回调。
基本上,您的组件代码应该如下所示:
getEmployeeInfo() { // requests extracted in constants for readability
const employeeNamesRequest = this.employeeService.getEmployeeNames();
const employeeDetailsRequest = this.employeeService.getEmployeeDetails();
forkJoin([employeeNamesRequest, employeeDetailsRequest])
.subscribe(data => {
this.employeeNames = data[0];
this.employeeDetails = data[1];
this.fillEmployeeDetails();
})
}
fillEmployeeDetails() {
this.employeeDetails.forEach(elem => {
let emp = this.employeeNames.find(employee => {
return (employee.employeeNumber === elem.employeeNumber);
});
let sup = this.employeeNames.find(supervisor => {
return (supervisor.employeeNumber === elem.supervisor);
});
let man = this.employeeNames.find(manager=> {
return (manager.employeeNumber === elem.manager);
});
elem.employeeName = emp.firstName + " " + emp.lastName;
elem.supervisorName= sup.firstName + " " + sup.lastName;
elem.managerName= man.firstName + " " + man.lastName;
});
}
首先,用我的实际代码解释起来有点混乱,所以我试图用一个更小的例子来简化问题。
假设我的项目从服务器中的 2 个不同 table 接收数据,employeeDetails 和 employeeNames。
employeeNames: 这个 table 有三列,employeeNumber, firstName , 和 lastName。顾名思义,这个 table 包含所有员工的列表,包括他们的名字和姓氏以及唯一的员工编号。
employeeDetails: 这个 table 是我从我的网站获取和 httpPost 数据的地方。例如,假设此 table 具有以下字段:
- employee:以员工号为输入
- 资格:让用户输入各种资格作为字符串
- 主管:取主管的员工编号,而不是姓名
- manager:采用经理的员工编号,而不是姓名
虽然后端是这种情况,但前端 employeeDetails 的接口有更多的成员。这就是它变得棘手的地方。
在前端,angular 界面是这样的:
export interface employeeDetails
{
employee: number;
qualifications: string;
supervisor: number;
manager: number;
employeeName: string;
supervisorName: string;
managerName: string;
}
所以,我使用 httpGet 从后端 api 获取数据,一旦我收到两个 table,我就有一个函数来填充 [=44= 中的额外字段]employeeDetails界面。
控制器
[HttpGet("[action]")]
public IActionResult getEmployeeNames()
{
using (var empApp= new EmployeeTable())
{
var empNames = new List<employeeNames>();
empNames = empApp.employeeNames.ToList();
return Json(empNames);
}
}
[HttpGet("[action]")]
public IActionResult employeeDetails()
{
using (var empApp= new EmployeeTable())
{
var empDetails = new List<employeeDetails>();
empDetails = empApp.employeeDetails.ToList();
return Json(empDetails);
}
}
服务
getEmployeeNames(): Observable<employeeNames[]> {
return this.http.get<employeeNames[]>(this.baseUrl + 'api/employeecontroller/getEmployeeNames')
.pipe(catchError(this.handleError('getItems', [])));
}
getEmployeeDetails(): Observable<employeeDetails[]> {
return this.http.get<employeeDetails[]>(this.baseUrl + 'api/employeecontroller/getEmployeeDetails')
.pipe(catchError(this.handleError('getItems', [])));
}
组件
getEmployeeInfo() {
this.employeeService.getEmployeeNames()
.subscribe(data => this.employeeNames = data);
this.employeeService.getEmployeeDetails()
.subscribe(data => this.employeeDetails = data);
fillEmployeeDetails();
}
fillEmployeeDetails() {
this.employeeDetails.forEach(elem => {
let emp = this.employeeNames.find(employee => {
return (employee.employeeNumber === elem.employeeNumber);
});
let sup = this.employeeNames.find(supervisor => {
return (supervisor.employeeNumber === elem.supervisor);
});
let man = this.employeeNames.find(manager=> {
return (manager.employeeNumber === elem.manager);
});
elem.employeeName = emp.firstName + " " + emp.lastName;
elem.supervisorName= sup.firstName + " " + sup.lastName;
elem.managerName= man.firstName + " " + man.lastName;
});
}
所以,当我试图调用这个函数时,它失败了。 原因是该函数甚至在获取整个 employeeNames table 之前就被调用了。如果没有获取 table,.find() 是 return 大量员工编号的空值,因此,我的函数没有 return 预期的结果。
我的问题
我应该使用 async/await 和 .toPromise() 并避免订阅该服务以等待获取数据,还是有更好的方法?
非常感谢任何帮助或想法。谢谢!
您必须订阅可观察对象才能发起 HTTP 请求。
此外,您不能像在代码片段中那样调用 this.fillEmployeeDetails();
,因为请求是异步的,数据需要一些时间才能返回 - 但是,您调用 this.fillEmployeeDetails
的代码行将被执行发出请求后立即。
当数据返回时,subscribe 中的回调函数以请求响应作为参数被调用。您必须在订阅内调用 this.fillEmployeeDetails();
,因为您会在那里接收数据。
但是你怎么知道两个请求是否已经返回,即你可以启动你的 fill...
函数吗?
最佳解决方案是使用 rxJs 运算符,例如 forkJoin,在这种情况下,它的行为类似于 Promise.all()。也就是说,它仅在所有可观察对象(在您的情况下为请求)都已完成执行时触发其在订阅内的回调。
基本上,您的组件代码应该如下所示:
getEmployeeInfo() { // requests extracted in constants for readability
const employeeNamesRequest = this.employeeService.getEmployeeNames();
const employeeDetailsRequest = this.employeeService.getEmployeeDetails();
forkJoin([employeeNamesRequest, employeeDetailsRequest])
.subscribe(data => {
this.employeeNames = data[0];
this.employeeDetails = data[1];
this.fillEmployeeDetails();
})
}
fillEmployeeDetails() {
this.employeeDetails.forEach(elem => {
let emp = this.employeeNames.find(employee => {
return (employee.employeeNumber === elem.employeeNumber);
});
let sup = this.employeeNames.find(supervisor => {
return (supervisor.employeeNumber === elem.supervisor);
});
let man = this.employeeNames.find(manager=> {
return (manager.employeeNumber === elem.manager);
});
elem.employeeName = emp.firstName + " " + emp.lastName;
elem.supervisorName= sup.firstName + " " + sup.lastName;
elem.managerName= man.firstName + " " + man.lastName;
});
}