【问题标题】:use async properly in typescript (angular)在打字稿中正确使用异步(角度)
【发布时间】:2021-07-07 12:39:35
【问题描述】:

我有一个部门列表,将从 API 链接获取。

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

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

我很困惑我应该把我的等待放在哪里

(注意:我的代码正在运行,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)

此外,在显示按钮单击时,我得到空值。

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

TIA

【问题讨论】:

  • 尝试同时删除asyncawait。您似乎提供了一个回调函数,因此可能会在数据准备好时调用它。
  • 这能回答你的问题吗? How can I `await` on an Rx Observable?
  • @nubinub 是的,我想要这样的东西,谢谢

标签: javascript angular typescript async-await observable


【解决方案1】:

RxJS observables 不依赖异步/等待功能,而是依赖订阅/回调模式。每当 UserServiceGetAllIndividualDepartment 方法返回的 observable 发出一个新值时,您的回调函数就会执行,因此不需要任何异步前缀。您可以以同步的方式访问数据,而无需使用 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 有何不同。

【讨论】:

    【解决方案2】:

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

    toPromise() 方法将为您处理订阅/取消订阅,并且只会在可观察对象完成时发出。对于 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());
    

    【讨论】:

    • 问题是:如果你想依赖Promise api,为什么要首先使用Observables
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-09
    • 1970-01-01
    • 2019-07-23
    • 2013-08-16
    • 1970-01-01
    • 2020-03-01
    • 2022-11-17
    相关资源
    最近更新 更多