Как перебрать метод подписки в Angular 5 - PullRequest
0 голосов
/ 02 мая 2018

Я пытаюсь перебрать метод подписки. Однако порядок, в котором данные помещаются в этот массив 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 голосов
/ 02 мая 2018

Это происходит потому, что цикл синхронизирован, а get - асинхронный. Таким образом, цикл не ждет, пока метод listFields завершит итерацию.

0 голосов
/ 02 мая 2018

вы делаете это неправильно, если у вас есть несколько запросов, а затем используйте mergeMap, сейчас проблема с вашим кодом заключается в том, что вы делаете асинхронный вызов для каждого идентификатора, и каждый занимает разное время для завершения (так что если вы хотите затем вы должны поместить данные в один массив и отсортировать их, нижеприведенное решение сделает это и для вас)

В вашем первом методе 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}`))
  );
}

Теперь, если вы хотите организовать по идентификатору, тогда вы должны сделать


Вы также можете использовать метод 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...