5

I have the following code in my service component, which gets me data from an api:

async getIngredientsByProductSubCategory(productSubCategoryId: number) {
    const url = '/my-url';
    let dataToReturn: any;
    await this.http.get(url).toPromise()
        .then(data => {
            console.log(data);
            dataToReturn = data;
        });
    return dataToReturn;
}

The problem is that the console.log above outputs the correct data, but when i execute it from another component like this:

this.myService.getIngredientsByProductSubCategory(4);

i get this output from my console.log:

log data of type "ZoneAwarePromise"

What do i have to do, to get the correct data in the other component? Do i have to resolve this in any way?

UPDATE:

Working solution for me:

Service:

getIngredientsByProductSubCategory(productSubCategoryId: number) {
    const url = '/my-url';
    return this.http.get(url).toPromise();
}

Component:

async getIngredients() {
    const ingredientsByProductSubCategory = await this.frontendService.getIngredientsByProductSubCategory(4);
}

Also i read that if you don't have the requirement to consume recurring data, you may not use Observables.

Thanks to all for your help!

Mikaelik
  • 355
  • 3
  • 4
  • 12
  • 1
    Why cant you just return Observable returned by http.get ?? – Antoniossss Apr 22 '20 at 17:26
  • You have to await `this.myService.getIngredientsByProductSubCategory(4)` – Jacob Apr 22 '20 at 17:26
  • Don't use `then` with `await`. Just do `dataToReturn = await this.http...`. – Heretic Monkey Apr 22 '20 at 17:26
  • Does this answer your question? [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) – Heretic Monkey Apr 22 '20 at 17:27
  • @HereticMonkey Does not change anything. Ive tried this before. I also read the article, but it didn´t help. I guess i'm missing something else here. I know how to rewrite it to make it work. But i want to know why the data (which obviously is there) is not returned correctly. – Mikaelik Apr 22 '20 at 17:34
  • Are you sure the console log you're seeing is the one you posted here and not from somewhere else? – Jacob Apr 22 '20 at 17:36
  • @Jacob Yes, my logging is correct! – Mikaelik Apr 22 '20 at 17:38
  • Then break each step down. Create a function that runs `return this.http.get(url);` Run that function, `getData`, and call it the normal Angular way, like `getData().subscribe(data => console.log(data))` see if the data is correct. If so, convert to promise and examine again, `var data = await getData().toPromise(); console.log(data);` see if the data is correct. Etc on up through the chain. – Heretic Monkey Apr 22 '20 at 17:49
  • @HereticMonkey Thank you, but i as i said is did this already! The data is not returned correctly when i call it from another component. – Mikaelik Apr 22 '20 at 17:53
  • You have not shown the code where you are calling it from the other component. The code you have shown uses the incorrect method for getting data using `await`. You can insist all you want that you've done this already, but we can see no evidence of that in your question. – Heretic Monkey Apr 22 '20 at 17:56

4 Answers4

6

.toPromise() is deprecated.

You should rather work with firstValueFrom or lastValueFrom.

Refer to this post for more details: Rxjs toPromise() deprecated

flawesome
  • 322
  • 3
  • 9
5

As you are declaring getIngredientsByProductSubCategory as async, automatically this method will return a Promise, so, all async, await or then are redundant here. We can simply write:

getIngredientsByProductSubCategory(productSubCategoryId: number) {
    const url = '/my-url';
    return this.http.get(url).toPromise();
}

and to consume that:

const ingredientsByProductSubCategory = await getIngredientsByProductSubCategory(someId);

Yasser Nascimento
  • 1,302
  • 7
  • 13
  • Thank you. That seems the correct way todo it. Also is have to declare the function in the other component as async when it is executed with await. – Mikaelik Apr 24 '20 at 10:33
1

.toPromise() is deprecated. Here is how to use the new lastValueFrom

Service

  Login(phone:string,password:string)
  {
    let _headers: HttpHeaders = new HttpHeaders({
      'accept': 'application/json'
    });
    return this.http.post(this.url,{username,password},{headers:_headers})
                .pipe(map(response=>response));
  }

Component

  async Login(phone:string,password:string)
  {
    let token$ =  this.authService.Login(phone,password);
    let token = await lastValueFrom(token$);
  }
Ashique Razak
  • 487
  • 3
  • 8
0

You can return observable instead of data. My solution is:

    getIngredientsByProductSubCategory(productSubCategoryId: number) {
      const url = '/my-url';
      return this.http.get(url);
}

To get data you need to subscribe to observable:

getIngredientsByProductSubCategory(4)
   .subscribe((data) => { dataToReturn = data; });
Aleksey
  • 36
  • 1
  • 2