代码之家  ›  专栏  ›  技术社区  ›  hxdef

角度4如何在分解器中返回多个观察值

  •  12
  • hxdef  · 技术社区  · 7 年前

    正如标题所述,我需要返回多个可观察到的或可能的结果。目标基本上是加载一个库列表,然后基于该库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();
        }
    }
    

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

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

    this.userService.getLibraryBooks(this.library["id"]).subscribe((response) => {
     // response processing
    })
    
    5 回复  |  直到 5 年前
        1
  •  13
  •   hxdef    7 年前

    我找到了一个解决这个问题的方法,也许会对某人有所帮助,所以基本上我使用了 forkJoin 组合多个观测值并解析所有观测值。

    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]
                };
            });
        };
    

    现在它工作正常,正如预期的那样。

        2
  •  6
  •   E_net4 Tunn    7 年前

    您可以使用 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)
          )
        );
      }
    }
    

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

    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 { }
    

    在接收组件中,您可以访问两个观察对象的快照,如下所示:

    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];
      }
    }
    
        3
  •  0
  •   Evonet    7 年前

    我也有类似的情况,但我的处理方式略有不同。

    在您的情况下,我的理解是您希望获得查询参数,然后根据响应调用更多的服务。

    我这样做的方式是让一个组件包裹其他组件,并传递它们所需的对象。我通过route paramMap订阅它们,然后将所有其他调用打包到a.Observalbe中。分叉连接

    在我的包装器组件中,我执行以下操作:

    ngOnInit() {
    
        this.route.params.subscribe((params) => {
            if (params.hasOwnProperty('id') && params['id'] != '') {
                const slug = params['slug'];
                Observable.forkJoin([
                    this.myService.getData(id),
                    this.myService.getOtherData(id),
                ]).subscribe(
                    ([data, otherData]) => {
                        this.data = data;
                        this.otherData = otherData;
                    },
                    error => {
                        console.log('An error occurred:', error);
                    },
                    () => {
                        this.loading = false;
                    }
                    );
            }
        });
    

    不完全是你想要的,但我希望它能为你指明正确的方向

        4
  •  0
  •   Nadhir Falta    7 年前

    我建议你使用可观察的东西,它们会让你的生活变得很轻松。 查看这两篇文章,了解如何使用可观察对象实现这一目标的更多详细信息:

    http://www.syntaxsuccess.com/viewarticle/combining-multiple-rxjs-streams-in-angular-2.0

    http://blog.danieleghidoli.it/2016/10/22/http-rxjs-observables-angular/

    我个人使用 flatMap

    祝你好运

        5
  •  0
  •   Raza Rizwan    3 年前
      resolve(route: ActivatedRouteSnapshot) {
    let id = route.params['id'];
    
    const getUser = new Promise((resolve, reject) => {
      this.customerService.getSingle(id).subscribe((res) => {
        resolve(res);
      }, (err) => {
        console.log('err', err);
      });
    });
    
    const getDocument = new Promise((resolve, reject) => {
      this.customerService.getDocument().subscribe((res) => {
        resolve(res);
      });
    });
    
    return Promise.all([getUser, getDocument]);
    

    }