Angular 4如何在解析器中返回多个可观察对象

hxd*_*def 5 angular-routing angular-http angular angular-httpclient

基本上如标题所述,我需要返回多个可观察值或一个结果。基本上,目标是加载并说出图书馆列表,然后根据该图书馆ID加载书籍。我不想在组件中调用服务,而是希望在页面加载之前先加载所有数据。

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot } from '@angular/router';
import { UserService } from './../_services/index';

    @Injectable()
    export class LibraryResolver implements Resolve<any> {

        constructor(private _userService: UserService) {}

        resolve(route: ActivatedRouteSnapshot) {
            return this._userService.getLibraryList();
        }
    }
Run Code Online (Sandbox Code Playgroud)

如何先加载图书馆列表,然后再加载每个图书馆的图书信息并返回到我的组件?

PS:我的服务通过ID加载了此方法

this.userService.getLibraryBooks(this.library["id"]).subscribe((response) => {
...
Run Code Online (Sandbox Code Playgroud)

hxd*_*def 11

我找到了这个问题的解决方案,也许会对某人有所帮助,所以基本上我已经习惯于forkJoin组合多个 Observable 并解决所有这些问题。

resolve(route: ActivatedRouteSnapshot): Observable<any> {
        return forkJoin([
                this._elementsService.getElementTypes(),
                this._elementsService.getDepartments()
                .catch(error => {

                    /* if(error.status === 404) {
                        this.router.navigate(['subscription-create']);
                    } */

                    return Observable.throw(error);
                })
        ]).map(result => {
            return {
                types: result[0],
                departments: result[1]
            };
        });
    };
Run Code Online (Sandbox Code Playgroud)

现在它按预期正常工作。


Gor*_*ant 6

您可以轻松地使用withLatestFrom.

这是 Stackblitz 中的一个工作演示:https ://stackblitz.com/edit/angular-xfd5xx

解决方法如下。

在您的解析器中,用于withLatestFrom组合您的可观察对象:

import { Injectable } from '@angular/core';
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { Library } from '../models/library.model';
import { LibraryBook } from '../models/library-book.model';
import { LibraryService } from '../services/library.service';
import { Observable } from 'rxjs';
import { withLatestFrom } from 'rxjs/operators';

@Injectable()
export class LibraryDisplayResolver implements Resolve<[Library, LibraryBook[]]> {

  constructor(
    private _libraryService: LibraryService,
  ) { }

  resolve (route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<[Library, LibraryBook[]]> {
    const libraryId = route.params['id'];
    return this._libraryService.getLibrary(libraryId).pipe(
      withLatestFrom(
        this._libraryService.getBooksFromLibrary(libraryId)
      )
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

确保您的解析器在您的路由中设置了适当的标识符:

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { LibraryDisplayComponent } from './library-display.component';
import { LibraryDisplayResolver } from '../resolvers/library-display.resolver';

const routes: Routes = [
  {
    path: ':id',
    component: LibraryDisplayComponent,
    resolve: {
      libraryResolverData: LibraryDisplayResolver
    }
  },
  {
    path: '',
    redirectTo: '1',
    pathMatch: 'full'
  },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class LibraryDisplayRoutingModule { }
Run Code Online (Sandbox Code Playgroud)

在接收组件中,您可以像这样访问两个 observable 的快照:

import { Component, OnInit } from '@angular/core';
import { LibraryBook } from '../models/library-book.model';
import { Library } from '../models/library.model';
import { ActivatedRoute } from '@angular/router';

@Component({
  // tslint:disable-next-line:component-selector
  selector: 'library-display',
  templateUrl: './library-display.component.html',
  styleUrls: ['./library-display.component.scss']
})
export class LibraryDisplayComponent implements OnInit {

  library: Library;
  libraryBooks: LibraryBook[];

  constructor(
    private route: ActivatedRoute
  ) { }

  ngOnInit() {
    this.library = this.route.snapshot.data['libraryResolverData'][0];
    this.libraryBooks = this.route.snapshot.data['libraryResolverData'][1];
  }
}
Run Code Online (Sandbox Code Playgroud)