在angular中,在组件中调用所有方法后调用订阅函数,这导致我无法使用响应

In angular, Subscribe function is called after all methods are called in the the component, this results that I am unable to use the response

我曾尝试用awaitasync来解决它,但作为打字稿的新手,我不习惯这些方法。 我这样使用 awaitasync

async refreshList(){
 await this.service.refreshList().subscribe(res => {
   console.log(res);
   this.service.todoListModel=res;
   });
}

通过调试和控制台输出了解到订阅方法参数代码是最后执行的。 请帮助修改我的以下组件代码:

import { Component, OnInit } from '@angular/core';
import { groupBy } from '@progress/kendo-data-query';
import { moveDown, slideIn, slideOut } from '../animations';
import { TodoService } from '../todo.service';

@Component({
  selector: 'todo',
  templateUrl: './todo.component.html',
  styleUrls: ['./todo.component.css'],
  providers: [TodoService],
  animations: [
    trigger('todoAnimations',[
      transition(':enter',[
        group([
          query('h1', [
            useAnimation(moveDown)
          ]),
          query('input', [
            useAnimation(moveDown)
          ]),
          query('@todoItem', [
            stagger(125, animateChild())
          ]),
        ])
      ])
    ]),
    trigger('todoItem', [
      transition(':enter', [
        useAnimation(slideIn)
      ]),
      transition(':leave',[
        useAnimation(slideOut)
      ])
    ])
  ]
})
export class TodoComponent implements OnInit {
  
  constructor(public service:TodoService) {
    this.refreshList(); 
    console.log(this.service.todoListModel);
    
  }
  
  ngOnInit(): void {
    this.organizeTodosByHour();
  }
    refreshList(){
      this.service.refreshList().subscribe(res => {
        console.log(res);
        this.service.todoListModel=res;
        });
    }
  organizeTodosByHour(){
    do
    {
      if(!this.service.todos) return null;
      this.service.hourlyTodos=groupBy(this.service.todos,[{field: "hour"}]);

      console.log(JSON.stringify(this.service.hourlyTodos,null,2));
      return 0;
    }
    while(this.service.todoListModel===[])
  }
  public onTimeChange(t:any){
    t.hour=t.due.getHours();
    this.organizeTodosByHour();
    console.log(this.service.todos,this.service.hourlyTodos);
  }
  addTodo(input: HTMLInputElement){
    this.service.todos=[{item:input.value, due: new Date(), hour:(new Date()).getHours()},...this.service.todos];
    input.value='';
    this.organizeTodosByHour();
  }
  removeTodo(i:number){
    this.service.todos.splice(i,1);
    this.organizeTodosByHour();
  }
}

请帮我解决我的问题。如果有人能向我解释如何使用 await 和 async,那将非常有帮助。

如果想使用async/await,可以使用convert observable来promise。有一个正在使用的方法,但已弃用 toPromise 而是使用 lastValueFrom.

import { lastValueFrom } from 'rxjs';

constructor(public service:TodoService) {
   (async () => {
         await this.refreshList();
         console.log(this.service.todoListModel);
   })();
  }

async refreshList(){
      const list$ = this.service.refreshList();
      this.service.todoListModel= await lastValueFrom(list$);;
}

对于特定情况还有其他 util observables 函数,您应该查看 this link 了解更多详情。

我看到你在构造函数中加载了列表,但你也可以在解析器中加载列表,数据将从一开始就存在于组件中,或者如果你想在此处执行此操作,只需将 Observable 转换为 Promise .

refreshList(): void {
    this.service.todoListModel =
       await this.service.refreshList().toPromise();
}

感谢你们的努力,Atlast 我确实理解了 awaitasync 方法,我最终得到了以下代码:

import { animateChild, group, query, stagger, transition, trigger, useAnimation } from '@angular/animations';
import { Component, OnInit } from '@angular/core';
import { groupBy } from '@progress/kendo-data-query';
import { moveDown, slideIn, slideOut } from '../animations';
import { TodoService } from '../todo.service';
import { lastValueFrom } from 'rxjs';

@Component({
  selector: 'todo',
  templateUrl: './todo.component.html',
  styleUrls: ['./todo.component.css'],
  providers: [TodoService],
  animations: [
    trigger('todoAnimations',[
      transition(':enter',[
        group([
          query('h1', [
            useAnimation(moveDown)
          ]),
          query('input', [
            useAnimation(moveDown)
          ]),
          query('@todoItem', [
            stagger(125, animateChild())
          ]),
        ])
      ])
    ]),
    trigger('todoItem', [
      transition(':enter', [
        useAnimation(slideIn)
      ]),
      transition(':leave',[
        useAnimation(slideOut)
      ])
    ])
  ]
})
export class TodoComponent implements OnInit {
  
  constructor(public service:TodoService) {
    this.refreshList(); 
    
  }
  
  ngOnInit(): void {
  }

  async refreshList(){
    const list$ = this.service.refreshList();
    this.service.todoListModel= await lastValueFrom(list$);
    console.log(this.service.todoListModel);
    this.service.todoListModel.forEach(element => {
      this.service.todos.push({item:element.itemName as string,due:(new Date(element.dueDate)),hour: (new Date(element.dueDate)).getHours()});
    });
    this.organizeTodosByHour();
}

  organizeTodosByHour(){
    if(!this.service.todos) return null;
      this.service.hourlyTodos=groupBy(this.service.todos,[{field: "hour"}]);
      console.log(JSON.stringify(this.service.hourlyTodos,null,2));
      return 0;
  }

  public onTimeChange(t:any){
    
    t.hour=t.due.getHours();

    this.organizeTodosByHour();
    console.log(this.service.todos,this.service.hourlyTodos);
    
  }

  addTodo(input: HTMLInputElement){
    this.service.todos=[{item:input.value, due: new Date(), hour:(new Date()).getHours()},...this.service.todos];
    input.value='';
    this.organizeTodosByHour();
  }

  removeTodo(i:number){
    this.service.todos.splice(i,1);
    this.organizeTodosByHour();
  }
}