完成两个Angular 2订阅后如何调用函数?

时间:2017-01-09 20:17:54

标签: javascript angular rxjs

我在Angular 2.3.1上,我对Angular和基于事件的编程都很新。我有两个订阅,route.params.subscribeengineService.getEngines()。在我的onInit我希望在getEngineNamethis.route.params.subscribe完成后致电this.engineService.getEngines().subscribe

原因:getEngineName函数取决于queryParams中的engineIdengines调用完成后填充的getEngines()数组。

我确实看过flatMapswitchMap,但我并没有完全理解它们。

这是组件中的代码:

export class ItemListComponent implements OnInit {
  items: Item[];

  engines: Engine[];
  private engineId: number;

  constructor(
    private router: Router,
    private route: ActivatedRoute,
    private itemService: ItemService,
    private engineService: EngineService
   ) {}

  ngOnInit() {
    this.route.params.subscribe((params: Params) => {
      this.engineId = +params['engineId'];

      // itemService is irrelevant to this question 
      this.itemService.getItems({engineId: this.engineId})
        .subscribe((items: Item[]) => {
          this.items = items;
        });
    });

    this.engineService.getEngines()
      .subscribe(engines => this.engines = engines);

    // This should only run after engineId and engines array have been populated.
    this.getEngineName(this.engineId);
  }

  getEngineName(engineId: number) {
    this.engines.find((engine) => {
      return engine.id === engineId;
    })
  }
}

2 个答案:

答案 0 :(得分:2)

为什么不在route.params回调中移动逻辑?

this.route.params.subscribe((params: Params) => {
      this.engineId = +params['engineId'];

      // itemService is irrelevant to this question 
      this.itemService.getItems({engineId: this.engineId})
        .subscribe((items: Item[]) => {
          this.items = items;
        });

     //this.engineId is defined here (1)
     this.engineService.getEngines()
      .subscribe((engines) => {
         this.engines = engines;
         //this.engines is defined here (2)
         this.getEngineName(this.engineId);
     });
});

flatMapforkJoin

this.route.params.flatMap((params: Params) => {
      this.engineId = +params['engineId'];    

      return Observable.forkJoin( 
         this.itemService.getItems({engineId: this.engineId}),
         this.engineService.getEngines()
      )          
}).subscribe((data)=>{
   let items = data[0];
   let engines = data[1];
   this.items = items;
   this.engines = engines;
   this.getEngineName(this.engineId);
});

答案 1 :(得分:0)

在这种情况下,建议使用

switchMap

    this.route.params.pluck('engineId') //pluck will select engineId key from params
        .switchMap(engineId => {
            this.getItems(engineId);
            return this.engineService.getEngines().map(engines => {
                /*this.engineService.getEngines() emits the list of engines.
                  Then use map operator to convert the list of engines to engine we are looking for
                 */
                return engines.find((engine) => {
                    return engine.id === engineId;
                })
            })
        }).subscribe(engine => {
          //engine  
    })

    getItems(engineId) {
      this.itemService.getItems({engineId: engineId})
        .subscribe((items: Item[]) => {
          this.items = items;
        });
    }

假设params中的engineId发生变化,第一个可观察的this.route.params.pluck('engineId')将发出数据,这将导致下一个可观察的this.engineService.getEngines()被触发。现在假设在此observable发出数据之前路由发生了变化。在这里,您需要取消getEngines observable以防止出错。这是由switchMap完成的。

如果触发了外部observable,

switchMap将取消内部observable。

PS:我避免保留this.engineId等任何状态。