0

So, I was trying to get the solution of this problem by using async/await. But, I am unable to do so, May be because of the lack of knowledge in angular. I have to access response values assigned in async fetchData() in component

The default values assign to employee is ALL

async function in component :

async fetchData(empId:string, empUrl:string) {
    this.message = "Fetching..";    
    this.resp = await this.http
      .get<any>(empUrl+empId)     
      .toPromise();
    this.message = "Fetched";
  }

function call :-

getEmployeeById(empId:string, empUrl:string){
    console.log("Get employee by empId....");    
    console.log("Before calling Employee API Call:");
    for (var obj of this.empResp) {
        console.log("empId   : " +obj.empId); 
        console.log("empName : " +obj.empName);  
    }

    console.log("************calling asynch call");
    this.fetchData(empId, empUrl);
    console.log("************back");

    console.log("After calling Employee API Call:");
    for (var obj of this.empResp) {
        console.log("empId   : " +obj.empId); 
        console.log("empName : " +obj.empName);          }
  }

on new employee values I have apply filters but not able to get the values out side async call.

Console OutPut :-

app.component.ts:65 Get employee by empId....
app.component.ts:66 Before calling employee API Call:
app.component.ts:68 empId   : ALL
app.component.ts:70 empName : ALL
app.component.ts:72 ************calling asynch call
app.component.ts:74 ************back
app.component.ts:76 After calling employee Archive API Call:
app.component.ts:78 empId   : ALL
app.component.ts:80 empName : ALL

app.component.ts:61 (3) [{…}, {…}, {…}]0: {empId: "123", empName: "XYZ"}1: {empId: "324", empName: "ABC"}length: 2__proto__: Array(0)

so after this run I want employees value as shown in response.

Please suggest.

SwapnilM
  • 67
  • 8
  • the question should be: "Why is the reason I need make a synchronous call?". It's a bad design. You should use Observables -not convert to promise- and rxjs operators if you want transform the response and, in subscription make "something" with the response – Eliseo Mar 12 '21 at 07:47
  • @Eliseo :- So I have situation I have 5 drop down, now on change event of one of the drop down values of other four is changing so now I want values of other four drop down and need to apply filters on that to show data on the data grid. So I am trying to get the records from API call and will get the required ID from response which will help to filter data. IF you have any better suggestion then please help. – SwapnilM Mar 12 '21 at 08:39

3 Answers3

0

This is the expected behavior. There is nothing wrong in your code. Your understanding on how it works is not correct.

Your function fetchData is "async" , it means it will be executed asynchronously. Inside fetchData you can execute multiple http requests and await for the response of each http request before you execute the next http request.

So, you need to move your code that you want to be executed after http request , inside fetchData

Agam
  • 865
  • 10
  • 20
0

I don't see the need here to convert the observable to promise. You could return the plain Observable and subscribe to it where the data is needed. And no, there is no way to convert an asynchronous call to a synchronous one.

Note: any statements that directly depend on the response from the async request must be inside the subscription. In other words, subscribe to the observable where it's response is required.

Please go through this answer and it's question to get a general idea of async requests.

import { finalize } from 'rxjs/operators';

fetchData(empId:string, empUrl:string) {
  this.message = "Fetching..";    
  this.http.get<any>(empUrl+empId).pipe(
    finalize(() => this.message = "Fetched"   // <-- triggered when the request is complete
  );
}

getEmployeeById(empId:string, empUrl:string){
  console.log("Get employee by empId....");    
  console.log("Before calling Employee API Call:");
  for (var obj of this.empResp) {
      console.log("empId   : " +obj.empId); 
      console.log("empName : " +obj.empName);  
  }

  console.log("************calling async call");
  this.fetchData(empId, empUrl).subscribe({
    next: (res: any) => {
      this.empResp = res;       // <-- assign result here
      console.log("************back");
      console.log("After calling Employee API Call:");
      for (var obj of this.empResp) {
        console.log("empId   : " +obj.empId); 
        console.log("empName : " +obj.empName);          
      }
    },
    error: (error: any) => {
      // handle error
    }
  });
}
Michael D
  • 20,838
  • 4
  • 12
  • 37
0

The whole point of using observable is to fetch a stream of data to one side from another side, in your case from server side to client. toPromise() is not recommended to use as you only fetch the first data in the stream, no more after that. So I recommend to keep the simple observable. Also it appears as you have a problem in passing values in the code. You can use the following code snippet as an example.

Observable fetches the whole array as I have experienced, at least that's how it looks like when you code, meaning the data you see in the code snippet is actually fetched by the server. There is an array, and its elements are objects. you can assign it to a variable, and then use for() with of to read their values. It's better you use return clause with HTTPClient.Get() to return the response, then read that response via an observable like HttpClient.Get().Subscribe(response => { console.log(response);})'

  public getEmployeeById() {
    let objArray = this.fetchData();
    for (let obj of objArray) {
      console.log("empId   : " + obj.empId);
      console.log("empName : " + obj.empName);
    }
  }

  fetchData() {
    return [
      { empId: 1, empName: "Don" },
      { empId: 2, empName: "Don2" },
      { empId: 3, empName: "Don3" }
    ];
  }
Don Dilanga
  • 1,702
  • 1
  • 11
  • 16