如何在Angular 5中循环使用subscribe方法

时间:2018-05-02 13:22:54

标签: angular

我试图遍历订阅方法。但是,在此数组this.fieldsList内推送数据的顺序并不一致。可能是什么原因?

import { Component, OnInit } from '@angular/core';
import {ActivatedRoute} from '@angular/router';
import { DragulaService } from 'ng2-dragula';
import {MatTableDataSource, MatDialog, MatDialogRef, MAT_DIALOG_DATA} from '@angular/material';
import { DataService } from '../../data.service';
import { ManufacturerAddTabComponent } from './manufacturer-add-tab/manufacturer-add-tab.component';
import { ManufacturerEditTabComponent } from './manufacturer-edit-tab/manufacturer-edit-tab.component';
import { ManufacturerDeleteTabComponent } from './manufacturer-delete-tab/manufacturer-delete-tab.component';
import { ManufacturerOrderTabsComponent } from './manufacturer-order-tabs/manufacturer-order-tabs.component';
import { ManufacturerAddFieldComponent } from './manufacturer-fields/manufacturer-add-field/manufacturer-add-field.component';
import { ManufacturerEditFieldComponent } from './manufacturer-fields/manufacturer-edit-field/manufacturer-edit-field.component';
import { ManufacturerDeleteFieldComponent } from './manufacturer-fields/manufacturer-delete-field/manufacturer-delete-field.component';

@Component({
  selector: 'app-manufacturer-tabs',
  templateUrl: './manufacturer-tabs.component.html',
  styleUrls: ['./manufacturer-tabs.component.css']
})
export class TabsComponent implements OnInit {

  manufacturerId;
  tabId;
  tabsList;
  fieldsList = [];
  rearrangedFields;

  constructor(private _dataService: DataService, public dialog: MatDialog, private route:ActivatedRoute, private dragulaService: DragulaService) {
    dragulaService.dropModel.subscribe((value) => {
      this.onDropModel(value);
    });
  }

  ngOnInit() {
    this.route.params.subscribe(res => this.manufacturerId = res.id);
    this.listTabs();
  }

  addTab(){
    let dialogRef = this.dialog.open(ManufacturerAddTabComponent, {
      width: '400px',
      data: { id: this.manufacturerId }
    });
    dialogRef.afterClosed().subscribe(result => {
      this.listTabs();
    });
  }

  editTab(tabId){
    let dialogRef = this.dialog.open(ManufacturerEditTabComponent, {
      width: '400px',
      data: { id: this.manufacturerId, tabId: tabId }
    });
    dialogRef.afterClosed().subscribe(result => {
      this.listTabs();
    });
  }

  deleteTab(tabId){
    let dialogRef = this.dialog.open(ManufacturerDeleteTabComponent, {
      width: '400px',
      data: { tabId: tabId }
    });
    dialogRef.afterClosed().subscribe(result => {
      this.listTabs();
    });
  }

  listTabs(){
    this.fieldsList = [];
    this._dataService.getManufacturerTabs(this.manufacturerId)
      .subscribe((response) => {
        this.tabsList = response;
        console.log(this.tabsList);
        for (let i=0; i<this.tabsList.length; i++){
          this.listFields(this.tabsList[i].id);
        }
      })
  }

  listFields(tabId){
    this._dataService.getManufacturerFields(tabId)
      .subscribe((response) => {
        this.fieldsList.push(response);
        console.log(this.fieldsList);
      })
  }

  orderTabs(){
    let dialogRef = this.dialog.open(ManufacturerOrderTabsComponent, {
      width: '400px',
      data: this.tabsList
    });
    dialogRef.afterClosed().subscribe(result => {
      this.listTabs();
    });
  }

  addField(tabId){
    let dialogRef = this.dialog.open(ManufacturerAddFieldComponent, {
      width: '400px',
      data: { id: tabId }
    });
    dialogRef.afterClosed().subscribe(result => {
      this.listTabs();
    });
  }

  editField(fieldId){
    let dialogRef = this.dialog.open(ManufacturerEditFieldComponent, {
      width: '400px',
      data: { id: fieldId }
    });
    dialogRef.afterClosed().subscribe(result => {
      this.listTabs();
    });
  }

  deleteField(fieldId){
    let dialogRef = this.dialog.open(ManufacturerDeleteFieldComponent, {
      width: '400px',
      data: { id: fieldId }
    });
    dialogRef.afterClosed().subscribe(result => {
      this.listTabs();
    });
  }

  onDropModel(args) {
      this.rearrangedFields = args[2].children;
      this.orderFields();
  }

  orderFields(){
    for(let i=0; i<this.rearrangedFields.length; i++){
      console.log(this.rearrangedFields[i].id + ' ' + (i+1));
      this._dataService.updateManufacturerFieldsOrder(this.rearrangedFields[i].id, i+1)
      .subscribe((response) => {
        console.log(response);
        this.listTabs();
      })
    }
  }
}

2 个答案:

答案 0 :(得分:3)

如果您有多个请求然后使用mergeMap,那么你的方法是错误的,现在问你代码是你正在为每个id做异步调用,每个都花费不同的时间来完成(所以如果你想要激活它然后你应该在一个数组中推送数据并对其进行排序,在解决方案下也可以为你做这个)

在第一个方法listTabs()中,代码如下

   const ids = [];
   for (let i=0; i<this.tabsList.length; i++){
      ids.push(this.tabsList[i].id);
    }
   this._dataService.getManufacturerFields(ids)
   .subscribe(item => {
    this.items.push(item);
    /*
      sort items by original IDs order 
      because responses might arrived in unordered fashion
      due to network conditions
    */
    this.items.sort((a: Item, b: Item) => {
       const aIndex = ids.findIndex(id => id === a.id);
       const bIndex = ids.findIndex(id => id === b.id);
       return aIndex - bIndex;
    })
  });

在您的服务方法中,您可以使用以下代码

getManufacturerFields(ids: number[]): Observable<any> {
  return from(ids).pipe(
    mergeMap(id => <Observable<any>> this.httpClient.get(`item/${id}`))
  );
}

现在如果你想按id安排那么你应该做

您还可以使用forkJoin方法为您发送请求提供输出,但此方法的问题是它等待所有请求竞争。

getManufacturerFields(ids: number[]): Observable<any> {
  return <Observable<any>> forkJoin(
    ids.map((id) => {
      return <Observable<Post>> this.httpClient.get(`item/${id}`);
    })
  ).pipe(concatAll());
}

这篇文章可能会对您有所帮助:https://blog.angularindepth.com/practical-rxjs-in-the-wild-requests-with-concatmap-vs-mergemap-vs-forkjoin-11e5b2efe293

答案 1 :(得分:0)

这是因为循环是同步的并且get是异步的。因此循环不会等待方法listFields完成迭代。