Home > Software engineering >  How to ensure one function does not run until after two functions?
How to ensure one function does not run until after two functions?

Time:01-25

In one component, I have two functions GetDataLabels() and GetData() that have subscriptions that return moderately-large amounts of data into multiple object arrays each. GetData() will sometimes need to be rerun due to user input, but GetDataLabels() will only need to be run once. The results of GetData()'s subscription have to be interpreted with the results of GetDataLabels(), ProcessData().

I am running into a problem where GetData()'s results cannot be processed because the results-processing part is trying to execute before GetDataLabels() has been completed. How can I ensure that ProcessData() (or GetData() if I put ProcessData()'s functionality in with GetData()) won't run until GetDataLabels() has completed?

EDIT: The code looks roughly like this:

export class MyPageComponent implements OnInit {

  column1labels: any[] = [];
  column2labels: any[] = [];

  data: any[] = [];

  column1display = [];
  column2display = [];

  ngOnInit() {
    GetDataLabels();
    GetData();
    ProcessData();
  }

  GetDataLabels() {
    this.service.getDataLabels().subscribe{
      data=> {
        this.column1labels = data['column1'];
        this.column2labels = data['column2'];
      }
    }
  }

    GetData() {
    this.service.getData().subscribe{
      data=> {
        this.data = data;
      }
    }

   ProcessData() {
     this.data.foreach(e => {
       //this is where I get the errors
       //column1labels and column2labels are still empty when this code runs
       column1display.push(column1labels.find(f=> f.label_id == e.col1_id));
       column2display.push(column2labels.find(f=> f.label_id == e.col2_id));
     })
   }
  }

}

CodePudding user response:

With what I understand you need to do a combineLatest between GetDataLabels & GetData. But I miss information just paste the code/stream considerate.

Often in such case when you become stuck in the stream considered is because you need to go upstream and redefine it though.

CodePudding user response:

You can simply forkJoin your requests as clearly you have to have labels and data before ProcessData

forkJoin({
   labels:this.service.getDataLabels(),
   data:this.service.getData()
}).subscribe(results=>{
    this.data=results.data;
    this.column1labels = results.labels.data['column1'];
    this.column2labels = results.labels.data['column2'];
    ProcessData(); //or even inline this as well.
})

CodePudding user response:

Since you mentioned "GetData() will sometimes need to be rerun due to user input, but GetDataLabels() will only need to be run once."; have you thought about calling these functions sequentially instead of calling them all from ngOnInit()? I'd suggest refactoring the code like below:

** Please read the comments I have added in your code**

export class MyPageComponent implements OnInit {

  column1labels: any[] = [];
  column2labels: any[] = [];

  data: any[] = [];

  column1display = [];
  column2display = [];

  ngOnInit() {
    GetDataLabels();
  }

  GetDataLabels() {
    this.service.getDataLabels().subscribe{
      data=> {
        this.column1labels = data['column1'];
        this.column2labels = data['column2'];
        // call GetData() when you have received the data from GetDataLabels()
        this.GetData();
      }
    }
  }

    GetData() {
    this.service.getData().subscribe{
      data=> {
        this.data = data;
        // call ProcessData() when you have received the data from GetData()
        // At this point you will already have the data from GetDataLabels() available
        /**
         * Since GetDataLabels() only need to be called once,
         * any time user input changes, you can just re-run GetData(),
         * without executing GetDataLabels() multiple times.
        */
        this.ProcessData();
      }
    }

   ProcessData() {
     this.data.foreach(e => {
       //this is where I get the errors
       //column1labels and column2labels are still empty when this code runs
       column1display.push(column1labels.find(f=> f.label_id == e.col1_id));
       column2display.push(column2labels.find(f=> f.label_id == e.col2_id));
     })
   }
  }

}
  • Related