解析器未返回 Firestore 的数据以加载 Angular 中的组件

Resolver not returning Firestore's data to load a component in Angular

我正在尝试延迟加载一个组件,并且我遵循了这个 Angular 指南(Angular Guide: Preloading component data),但我什至没有从解析器取回数据,所以该组件未显示。让我们到我的平面简单代码:

服务

export class OrdersService {
  constructor(private firestore: AngularFirestore, private http: HttpClient) {}

  getCoffeeOrders() {
    // return request = this.http.get('http://date.jsontest.com/'); // Works, but it's not the right data
    return this.firestore.collection<CoffeeOrder>('coffeeOrders').valueChanges();;
  }
}

解析器

import { Injectable } from '@angular/core';
import {
  Resolve,
  ActivatedRouteSnapshot,
  RouterStateSnapshot,
} from '@angular/router';
import { Observable } from 'rxjs';
import { CoffeeOrder, OrdersService } from './shared/orders.service';

@Injectable({
  providedIn: 'root',
})
export class GetCoffeeOrdersResolverService implements Resolve<CoffeeOrder[]> {
  constructor(private ordersService: OrdersService) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<CoffeeOrder[]> | any {
    console.log('GetCoffeeOrdersResolver');

    return this.ordersService.getCoffeeOrders();
  }
}

组件

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
@Component({
  selector: 'app-order-list',
  templateUrl: './order-list.component.html',
  styleUrls: ['./order-list.component.css'],
})
export class OrderListComponent implements OnInit {
  coffeeOrders;
  res;
  constructor(private route: ActivatedRoute) {}

  ngOnInit() {
    console.log('ngOnInit');
    this.route.data.subscribe(res => {
      console.log(res);
      this.res = res;
    })
  }
}

路由选择

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { GetCoffeeOrdersResolverService } from './get-coffee-orders-resolver.service';
import { OrderListComponent } from './order-list/order-list.component';

const routes: Routes = [
  {
    path: '',
    component: OrderListComponent,
    resolve: { orders: GetCoffeeOrdersResolverService },
  },
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule],
})
export class AppRoutingModule {}

我的结构版本

Angular CLI: 10.1.7
Angular: 10.1.6
Agular Fire: 6.0.3
rxjs: 6.6.3
typescript: 4.0.3

This is my Gist with the files

我发现请求没有被解析器结束后尝试了一些东西,所以解决这个问题的关键是在我的解析器中用一个变通管道完成请求。

export class GetPatientsResolverService implements Resolve<Patient[]> {
  constructor(private patientService: PatientService) {}

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Observable<Patient[]> {
    return this.patientService
      .getPatients()
      .valueChanges({ idField: 'id' })
      .pipe(take(1)); // HERE IS THE TRICK!
  }
}

管道调用中的 take(1) 方法终止请求,然后可以等待将其带到解析器和正确服务的答案。

为什么使用 take() 而不是 first()?

基本上:

  • take(n) 不贪心,所以会尝试 return 集合中的前 n 个元素,如果集合为空则不会抛出一个错误。
  • first() 是贪婪的,并确保它将 return 恰好一个元素或抛出错误