如何等待服务加载数据完成?

时间:2019-09-18 03:32:20

标签: angular async-await

我想从组件构造器中的角度服务加载数据,并使用这些数据更新ngOnInit()函数中的UI。

我正在使用async-await功能来实现它。

不幸的是,它不起作用。

这是我的组件源代码:

import { Component, OnInit } from '@angular/core';
import {MonthlyCalendar} from './monthly-calendar';
import { MonthlyCalendarService } from './monthly-calendar.service';
import { resolve } from 'url';
@Component({
  selector: 'app-table',
  templateUrl: './table.component.html',
  styleUrls: ['./table.component.css']
})
export class TableComponent implements OnInit {
  monthlyCalendar: MonthlyCalendar;
  constructor(private monthlyCalendarService: MonthlyCalendarService) {
    this.monthlyCalendar = null;
    console.log('t0:' + new Date());
    this._getData();

    console.log('t2:' + new Date());
  }

  ngOnInit() {
    console.log('t3:' + new Date());
    console.log(this.monthlyCalendar);
  }
  async _getData() {

    await this.monthlyCalendarService.getMonthlyCalendar(null, null)
    .then((data: MonthlyCalendar) => {
      console.log('t1:' + new Date());
      this.monthlyCalendar = data;
    })
    .catch ((err: Error) => {
      alert(err.stack);
    });
  }
}

这是我的服务源代码:

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse, HttpParams } from '@angular/common/http';
import { MonthlyCalendar } from './monthly-calendar';
import { resolve, reject } from 'q';

@Injectable({
  providedIn: 'root'
})
export class MonthlyCalendarService {

  constructor(private http: HttpClient) { }
  getMonthlyCalendar(year: number, month: number): Promise<object> {
    const params = new HttpParams();
    if (year != null) {
      params.set('year', year.toString());
    }
    if (month != null) {
      params.set('month', month.toString());
    }
    return this.http.get('backend/getMonthlyCalendar.php', {params}).toPromise();
  }
}

这是我的component.html

<table>
  <theader></theader>
  <tbody></tbody>
</table>

我附上了屏幕转储,供您参考。

4 个答案:

答案 0 :(得分:1)

您可以使用解析器在组件加载之前加载数据,直到解析数据请求后才会加载路由,以下是解析器的一些示例

https://codeburst.io/understanding-resolvers-in-angular-736e9db71267

https://alligator.io/angular/route-resolvers/

因此,首先创建一个类似的解析器

import { Injectable } from '@angular/core';

import { Resolve } from '@angular/router';

import { Observable } from 'rxjs';
import 'rxjs/add/observable/of';
import 'rxjs/add/operator/delay';

@Injectable()
export class CalendarResolver implements Resolve<Observable<string>> {
  constructor(private monthlyCalendarService: MonthlyCalendarService) {}

  resolve() {
    return this.monthlyCalendarService.getMonthlyCalendar(null, null);
  }
}

然后将此解析器添加到您的路线

import { CalendarResolver } from './claendar.resolver';

   {
    path: 'yourpath',
    component: yourcomponent,
    resolve: { calander: CalendarResolver }
    }

将您的解析器添加到模块的提供者数组中

然后在您的组件中

   constructor(private activatedRoute: ActivatedRoute)

   ngOnInit(){
    this.monthlyCalander= this.route.snapshot.data['calander'];
   }

答案 1 :(得分:0)

您可以为此使用解析器

@Injectable()
export class MyResolver implements Resolve<SomeClass[]> {
    constructor(private myService: MyService) {
    }

    resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<SomeClass[]> {
        return this.myService.getAll().pipe(first());
    }
}

在路由器中,您可以注册解析器。

        {
            path: 'somepath',
            component: MyComponent,
            resolve: {
                objects: MyResolver ,
            }
        },

然后,您可以像下面在组件中一样访问已解析的数据。

ngOnInit(): void {
    this.route.data.subscribe((data: any) => {
        this.objects = data['objects'];
    });
}

答案 2 :(得分:0)

您必须在构造函数中更改这样的代码

this._getData().then(() =>  
      console.log('t2:' + new Date()
      ))

答案 3 :(得分:0)

Angular有一个非常不错的模块HTTPClientModule。这是建立在RxJS Observable包的顶部。

HTTPClientModule之类的方法,例如get方法,返回observable,我们可以在组件中进行订阅,并通知视图以更新DOM。

请阅读官方documentation