0

I am facing an issue with response from HTTP request in Angular 2. I am using ".subscriber" to get the response of the HTTP request.

Following is the code I have written :

NewJobDetailsComponent.ts :

ngOnInit() {
  this.masterData = this.masterDataS.getMasterData(["designations"]);
//code breaking at below line
  this.designations = this.masterData["designations"]; 
}

MasterDataS.ts :

private masterData = {};
private baseUrl = "some URL";
getMasterData(keys) {
  let missingData = [];
  for (let key of keys) {
    this.baseAjaxService.doPost(this.baseUrl, missingData)
        .subscribe(data => {
              this.masterData[key] = data[key];
              this.sessionStorage.setValue(key, data[key]);
        });
  }
  return this.masterData;
}

In the above code, I fetch some data from server, after which I have to use the result to assign to this.designations.

Now to make the service commonly usable I have to use .subscriber for this request in MasterDataS.ts. Hence I am not able to write the .subscriber in NewJobDetailsComponent.ts

But as the code in NewJobDetailsComponent.ts depends upon the result of the HTTP request. How can I write the code in synchronous manner so that after getting the result of the HTTP only below statement will be executed??

this.designations = this.masterData["designations"]; 

This kind of issue I am getting at most of the times where the example only changes.

Liam
  • 27,717
  • 28
  • 128
  • 190
Ricks
  • 369
  • 3
  • 7
  • 20
  • [Please don't put tags in question titles](https://stackoverflow.com/help/tagging) – Liam Jun 15 '17 at 12:44
  • 1
    Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Liam Jun 15 '17 at 12:46
  • @Liam : I am having this issue perticularly in Angular2. Above link is not having anything related to Angular 2. – Ricks Jun 16 '17 at 10:22
  • 1
    @Ricks - your question (and answer) is generic and all based on the same principals of how to make async calls in javascript. Once you understand the fundamentals of the answer as explained in that article it could be any asynch library. Angular2 utilizes RxJs but this library also supports Promise (using toPromise()) which is explained in the above duplicate answer. Please read through the answers provided in the duplicate. – Igor Jun 16 '17 at 10:31
  • This isn't an angular issue (per se) this is a javascript issue – Liam Jun 16 '17 at 10:32

1 Answers1

-1

You have to refactor your code to achieve a stable async code handling.

// javascript Async mixed with Sync code?

getMasterData(keys) {
  console.log(1);

  let missingData = [];
  for (let key of keys) {
    console.log(2);

    this
    .baseAjaxService
    .doPost(this.baseUrl, missingData)
    .subscribe(data => {
        console.log(3);

        this.masterData[key] = data[key];
        this.sessionStorage.setValue(key, data[key]);
    });
  }

  console.log(4);
  return this.masterData;
}

// but instead you get
// 1
// 2 x keys lenght
// 4
// 3 x resolved times

As someone asks, this is the solution to your issue, but, keep in mind, understanding async code execution is one of the main concepts in javascript, so, I suggest you to don't copy my code but do it by yourself:

getMasterData(keys) {

  return Promise
    .all(
      keys
        .map(() => (
          this
            .baseAjaxService
            .doPost(this.baseUrl, missingData)
            .toPromise()
            .then(data => data[key])
        ))
    )
  ;
}


// Component

ngOnInit() {
  this.masterData = this
    .masterDataS
    .getMasterData(["designations"])
    .then(results => {
      this.designations = results["designations"]
      // do whatever you want with this.designations
    })
  ;
}
Hitmands
  • 13,491
  • 4
  • 34
  • 69
  • 1
    `return this.masterData;` isn't going to work. This suffers from the [same issue](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) the question does – Liam Jun 16 '17 at 10:33
  • `this.masterData[key] = data[key];` will be executed later than `this.designations = this.masterData["designations"];`, so, instead of downwoting... try to understand how the event loop works. – Hitmands Jun 16 '17 at 10:34
  • What? I have no idea what your trying to say here? yes, `this.masterData[key] = data[key];` will be executed later than `this.designations = this.masterData["designations"];`, that is the OPs issue. How does what you've put above solve this? – Liam Jun 16 '17 at 10:37
  • All you've done is reformat the code a bit and add some console messages?! – Liam Jun 16 '17 at 10:40
  • I have highlighted the issue showing him on what order its code will run, then, he needs to refactor that code... – Hitmands Jun 16 '17 at 10:42
  • But not actually answered the issue? – Liam Jun 16 '17 at 10:42
  • 1
    I do not see how this answer is in any way helpful and then even more so if you look at the answers provided in the duplicate question link. – Igor Jun 16 '17 at 10:46