在 Angular 中获取(HTTP-Get)多个 class 个对象

Fetch(HTTP-Get) multiple class objects in Angular

首先,用我的实际代码解释起来有点混乱,所以我试图用一个更小的例子来简化问题。

假设我的项目从服务器中的 2 个不同 table 接收数据,employeeDetailsemployeeNames

employeeNames: 这个 table 有三列,employeeNumber, firstName , 和 lastName。顾名思义,这个 table 包含所有员工的列表,包括他们的名字和姓氏以及唯一的员工编号。

employeeDetails: 这个 table 是我从我的网站获取和 httpPost 数据的地方。例如,假设此 table 具有以下字段:

虽然后端是这种情况,但前端 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;

    });
}