在打字稿中正确使用异步 (angular)

use async properly in typescript (angular)

我有一个部门列表,将从 API link 中获取。

当我的 angular 应用程序加载时(我的意思是在 ngOnInit(): void 调用之后),我想要:

  1. 我将获取所有部门 async
  2. 那我就await给所有部门加载
  3. 最后,我会将第一个部门的 id 保存在一个变量中

我很困惑我应该把 await 放在哪里

(注意:我的代码正在运行,API 响应出现,我只卡在等待部分)

这是我尝试的程度:

app.component.ts:

import { Component, OnInit } from '@angular/core';
import { DepartmentModel } from '../../user/models/individual-department.model';

@Component({
  selector: 'app-requisition-report-one',
  templateUrl: './requisition-report-one.component.html',
  styleUrls: ['./requisition-report-one.component.css']
})
export class RequisitionReportOneComponent implements OnInit {

  displayIndividualDepartmentList: DepartmentModel[] = [];

  currentDisplayDepartment: number = null;


  constructor(private userService: UserService) { }

  ngOnInit(): void {
    this.initializeDepartmentList();
  }


  initializeDepartmentList() {
    this.userService.GetAllIndividualDepartment().subscribe(
      async (data: DepartmentModel[]) => {
        this.displayIndividualDepartmentList = data;
        this.currentDisplayDepartment = await this.displayIndividualDepartmentList[0].department_id;
      }
    );
  }

  onShowButtonClick() {
    console.log(this.currentDisplayDepartment);
  }

}

我的 vscode 给我这样的警告

'await' has no effect on the type of this expression.ts(80007)

此外,点击显示按钮时,我得到的是空值。

我想在 await 加载列表后从列表 displayIndividualDepartmentList 中获取此变量 currentDisplayDepartment 中第一个部门的 ID。

TIA

RxJS observables 不依赖于 async/await 特征,而是依赖于 subscription/callback 模式。每当 GetAllIndividualDepartment 方法从 UserService 返回的可观察对象发出新值时,您的回调函数将被执行,因此不需要任何异步前缀。您可以以同步方式访问数据,而无需使用 await 关键字。

 initializeDepartmentList() {
    this.userService.GetAllIndividualDepartment().subscribe(
      (data: DepartmentModel[]) => {
        this.displayIndividualDepartmentList = data;
        this.currentDisplayDepartment = this.displayIndividualDepartmentList[0].department_id;
      }
    );
  }

A quick explanation of RxJS observables 以及它们与您习惯使用的 Promise 有何不同。

您可以将 Observable 转换为如下所示的承诺,并使用 async/await 语法而不是 .then() 语法。

toPromise() 方法将为您处理 subscribe/unsubscribe,并且只会在可观察对象完成时发出。在 HTTP 可观察对象的情况下,它们通常只发出一个值(原始值或其他值)然后完成。

然后您可以使用所示的 async/await 语法或使用 .then()。

将 toPromise() 与 HTTP 可观察对象一起使用是一种非常引人注目且简洁的语法,使异步代码看起来同步且更易于理解。

  async initializeDepartmentList(): Promise<void> {
    const data: DepartmentModel[] = await this.userService.GetAllIndividualDepartment().toPromise();
    this.displayIndividualDepartmentList = data;
    this.currentDisplayDepartment = this.displayIndividualDepartmentList[0].department_id;
  }

这样调用...

async ngOnInit(): Promise<void> {

    await this.initializeDepartmentList();
.
.
}

或者像这样的自调用函数。


ngOnInit()
{
(async () => {
  await this.initializeDepartmentList();
})()
}

只是要补充一点,toPromise 在 RxJS 7 中已被弃用,并将在 RxJS 8 中删除。

您可以使用 lastValueFrom

const data = await lastValueFrom(this.userService.GetAllIndividualDepartment());

附带说明一下,如果您想在启动时初始化您的应用程序,您可以使用...

app.module.ts

providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: appInitializeService,
      multi: true
    },

像这样。返回无效的承诺。在继续之前,该应用程序有效地等待您的先决条件加载。

export const appInitializeService = (): () => Promise<void> => (): Promise<void> => new Promise((resolve) => resolve());