No data being displayed or returned from API when using async await

My Ionic 6 + Angular 14 application is currently facing an issue with displaying data retrieved from an API...

I have implemented a service to fetch the data from the API and then called this service in the component. The app compiles without any errors and there are no console errors in the browser...

I am seeking assistance in identifying where I may have made a mistake?

Below is the code snippet for my service:

async getCategories() {

 const token = await Preferences.get({ key: 'TOKEN_KEY' });

 const headers = new HttpHeaders().set('Authorization', `Bearer ${token.value}`);
 this.httpClient.get(`${environment.apiUrl}categories`, {headers}).subscribe(
 data => {
 this.categories = data;
    },
 error => {
 console.log('Error', error);
    }
  );
}

And here is the relevant code from the component.ts file:

ngOnInit() {
 this.getCategories();
}

getCategories() {
 this.categories = this.categoriesService.getCategories();
}

Answer №1

When working with a mix of Promise and Observable, several issues can arise. It is advised to stick to using Observables whenever possible. In your specific scenario, you have replaced it with.

 async getCategories() {
 const token = await Preferences.get({ key: 'TOKEN_KEY' });

 const headers = new HttpHeaders().set('Authorization', `Bearer 
 ${token.value}`);
 try { 
   const categories = await lastValueFrom(this.httpClient.get(`${environment.apiUrl}categories`, {headers}));
   return categories;
   catch(err) {
     // log error
 }
}
}

This method will provide a Promise containing the data.

The most effective approach is to leverage the advantages of rxjs by utilizing solely Observables.

getCategories() {
    return from(Preferences.get({ key: 'TOKEN_KEY' })).pipe(
        switchMap(token => {
            const headers = new HttpHeaders().set('Authorization', `Bearer ${token.value}`);
            return this.httpClient.get(`${environment.apiUrl}categories`, {headers})
        })
    );
};

In your component, you should have a variable that holds the Observable like so:

 this.categories$ = this.yourService.getCategories();

Then in your template, make use of the async pipe, for instance:

 <div *ngFor="let category of categories$ | async">
   <p>{{ category }}</p>
 </div>

I also suggest exploring Interceptors in Angular as it is a great place to include the Authorization token.

Best of luck :)

Answer №2

To effectively manage observables, it is important to subscribe to them within the component rather than the service. The service should solely be responsible for returning the observable. Additionally, remember that any asynchronous function will return a Promise which needs to be handled with either await or .then()

Service:

async getCategories() {
 const token = await Preferences.get({ key: 'TOKEN_KEY' });

 const headers = new HttpHeaders().set('Authorization', `Bearer ${token.value}`);
 return this.httpClient.get(`${environment.apiUrl}categories`, {headers});
}

Component:

ngOnInit() {
 this.getCategories();
}

getCategories() {
 this.categoriesService.getCategories().then(categoriesObservable => 
    categoriesObservable.subscribe(data => {
      this.categories = data;
    },
    error => {
      console.log('Error', error);
    }
  );
}

Answer №3

Assigning a variable the result of .getCategories() is not valid because this method does not have a return value.

Answer №4

It appears that there may be a gap in your understanding, I recommend reviewing the tour of heroes at this link: https://angular.io/tutorial

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Guide on displaying the length of an observable array in an Angular 2 template

I am working with an observable of type 'ICase' which retrieves data from a JSON file through a method in the service file. The template-service.ts file contains the following code: private _caseUrl = 'api/cases.json'; getCases(): Obs ...

Generating an interactive table using JSON with Angular 5

Can a dynamic table with dynamic columns be created based on a JSON object using Angular 5? If yes, how? The API response includes the following JSON: { "ResponseStatus": true, "ResponseData": [ { "Parent": "Company 1", ...

What is the best way to refresh data in a React component so that it displays the recently added data?

My website features a todo list that functions like this: Todo list Upon clicking the plus button, an input field appears allowing users to add items. Although the item is successfully added to the database, it does not immediately reflect on the webpage ...

React: State updates are not reflecting in the UI components

I am facing an issue where a function component is not updating visually when the state changes. To illustrate this problem, I have included a simple example of my component in which I update the state but the component does not reflect these changes in t ...

Guide to activating the timer specifically on select pages with jQuery Mobile

I've developed a quiz application using jQuery Mobile and I am working on implementing a timer feature. The timer should run from 0 seconds up to 1 hour but only when the user is viewing specific pages, specifically the question pages. The timer is di ...

Guide to extracting the key of a JSON object with a numerical name

I am having trouble extracting JSON objects from my server that contain numbered names to distinguish them. When trying to retrieve these objects, I encounter an issue with appending numbers to the common name. The structure of the objects is as follows: ...

Ensure that the main div remains centered on the page even when the window size is adjusted

Here is the code snippet: <div id="root"> <div id="child1">xxxx</div> <div id="child2">yyyy</div> </div> CSS : #root{ width: 86%; margin: 0 auto; } #root div { width: 50%; float: left; border: ...

The autocomplete feature is now bypassing any text that comes after the #

return this.http.get(Configs.BASE_PATH + 'getTaxRates' + query + '&ts='+ Date.now()); query = "? The problem I'm encountering is related to my search query: 303 E 14 mile Rd, #305, Clawson, MI 48017. This ...

Is it feasible to develop a Grafana datasource plugin that does not rely on an external backend system?

I am in the process of developing a Grafana datasource plugin that operates independently without relying on an external backend. My plugin is based on the simple-json datasource plugin available at: https://github.com/grafana/simple-json-datasource In a ...

The width of the plotbands on the yAxis of a stacked bar graph is adjusting as the series are dynamically toggled,

https://ibb.co/h7tmwtr https://ibb.co/syRTyPG For the first time, I have included 5 plot bands which looked great. However, when I added a series and toggled it on a stacked bar graph, the plot bands' width started increasing. I want to maintain the ...

Is it necessary to include a request in the API route handler in Next.js when passing parameters?

In my API route handler, I have a function for handling GET requests: import { NextRequest, NextResponse } from "next/server"; export async function GET(req: NextRequest, { params }: { params: { id: string } }) { const { id } = params; try { ...

Ways to retrieve parameters in getStaticPaths function?

I'm currently working on a Next.js app with Contentful as the CMS. The file structure relevant to my question is: pages -[category] -[slug].js My goal is to access the category value when a user visits category/slug. Currently, I have the category ...

Using jQuery to target adjacent elements excluding those that are separated by other text

I have been attempting to locate and combine adjacent em tags within paragraphs, but it has proven to be a more challenging task than I initially anticipated. Let's explore some examples to illustrate this issue: <p><em>Hello</em>&l ...

Tips for positioning input fields and labels in both horizontal and vertical alignment

Below is the HTML code, and I want the tags to look like this: label1: input1 label2: input2 label3: input3 Instead, it currently looks like this: label1: input1 How can I modify the HTML to achieve the desired format? HTML: <div class=" ...

When using jQuery, the search for the ID within an iframe may fail if the specified condition

I have a scenario where I need to dynamically generate an iframe and its corresponding id. Now, I need to check if the generated id already exists or not. This is what my code looks like: function createIframe(intxnId){ alert("The Id is : "+"$(&apo ...

Next.js encountered an API resolution issue while uploading a file, resulting in no response being

Even though my code is functioning properly, a warning appears in the console: The API call was resolved without sending any response for /api/image-upload This particular endpoint is responsible for uploading an image to Digital Ocean's object sto ...

Managing PHP and AJAX: Strategies for handling and transmitting error responses

There are three main components involved in this process: An HTML form The AJAX connection that transmits the form data and processes the response from the PHP script The PHP script, which evaluates the data received, determines if it is valid or not, an ...

Getting a Cookie in React from an Express JS API (MERN Stack)

My API in Express JS stores a token in a cookie on the client-side (React). The cookie is generated only when a user logs into the site. When testing the login API with Postman, the cookie is generated as expected: https://i.sstatic.net/rL6Aa.png However ...

Styling for older versions of Internet Explorer (IE10 and earlier)

Could it be true that IE 10, 9, and others no longer support conditional statements? Is it also accurate to say that JQuery does not support the browser object above version 1.9? I am facing an issue with CSS rendering differently in Chrome and IE. A Goog ...

Does the frame take precedence over the button?

const div = document.createElement('div'); // creating a dynamic div element div.setAttribute('id', "layer1"); // setting an id for the div div.className = "top"; // applying a customized CSS class div.style.position = "absolute"; // sp ...