Directly retrieve the result from http service (observable) without the need to return Observable from the function

Is there a way to directly return a result from the service without returning Observable and then using then clause? I've experimented with methods like pipe, of, take, toPromise, map, async-await, but none of them seem to return the result on a service call. Some of these methods aren't even available in the current version of RxJS. Can you provide any assistance?

Note: There is a condition where if the API fails, I need to retrieve data locally.


@Injectable()
export class SomeService {
  GetDataEitherFromApiOrFromLocalStorage(): any 
  {
    let result;
    this.http.get("https://"+ this.url +"/api/main/apidata").subscribe(
       next => {result = next;},
       error => {result = this.localData();},  
       () => {return result;}
    )
  }
}

When calling the function (which currently returns null, even with async-await)


@Component()
export class SomeComponent implements OnInit {

  constructor(private service: SomeService) {}

  ngOnInit() {
   let data = this.service.GetDataEitherFromApiOrFromLocalStorage();
  }
}

UPDATE:

I'm attempting this because I'd like to keep all the logic within the Service, rather than in the Component.

Answer №1

If you're looking for a solution, consider the following approach:

Both the promise route (at the end) and the observable route have been included.

Keep your api/data operations isolated in the service - components shouldn't be concerned with the implementation details.

GetDataEitherFromApiOrFromLocalStorage(): Observable<any> {
    return this.http.get('https://' + this.url + '/api/main/apidata').pipe(
        catchError((error) => {
            // Check if error is critical or expected
            let errorIsNotFatal = true;
            if (errorIsNotFatal) {
                return this.localdata(); // this function should return an observable;
            }
            return throwError(error);
        })
    );
}

Note: The catchError() block will handle both fatal errors and expected ones by fetching local data if needed.

        catchError((error) => {
           // Evaluate if error is fatal or expected
            errorIsNotFatal = true;
            if (errorIsNotFatal) {
                return this.localdata(); // this should return an observable;
            }
            return throwError(error);
        })

In order for localData() to work, it must also return an observable:

localdata(): Observable<any> {
    return of('anything or any kind of data');
}

Simply subscribe in your component and wait for the response:

export class SomeComponent implements OnInit {
    public data: any;

    constructor(private service: SomeService) {
    }

    ngOnInit() {
        this.service.GetDataEitherFromApiOrFromLocalStorage().subscribe((response) => {
            this.data = response;
        });
    }
}

Lastly - If you truly need a promise, you can create one like this. However, using observables is recommended over promises:

GetDataEitherFromApiOrFromLocalStorage(): Promise<any> {
    return new Promise((resolve, reject) => {
        this.http.get("https://" + this.url + "/api/main/apidata").subscribe(
            (next) => { resolve(next); },
            (error) => { reject(error); }
        );
    });
}

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

Communicate between sibling components in Angular by passing the selector of one component to another

Within my project, I have two sibling components located in the SecondComponent folder. The SecondComponent consists of both the main component and its child component. Now, in the FirstComponent, I need to access the child component of the SecondComponent ...

Tips for acquiring the newest router in an angular environment

Is there a way to retrieve and store the URL of the latest router that the user has visited in local storage? Any suggestions would be greatly appreciated. Thank you! ...

What is the best way to trigger a method after an old component has been removed from the DOM while navigating within Angular

I am facing a challenge where I need to execute a method on ComponentB after a routerLink is clicked, causing the navigation from ComponentA to ComponentB. It is crucial that this method is triggered only after the entire navigation process is complete (i. ...

The message "Expected a string literal for Angular 7 environment variables" is

I'm currently working on setting up different paths for staging and production environments in my Angular project, following the documentation provided here. I have a relative path that works perfectly fine when hardcoded like this: import json_data f ...

What is the best way to utilize namespaces across multiple files in your program

I am currently working with TypeScript 1.6.2 and atom-typescript. In my project, I'm attempting to utilize namespaces across separate files: // Main.ts import * as _ from 'lodash' namespace Test { export var value = true } // Another.ts ...

Transforming Javascript into Typescript with node modules in Visual Studio 2015

After developing a JavaScript web app using npm and webpack, I successfully converted all the .js files to .ts using the PowerShell command found here. Now, I am looking to transition to a VS2015 TypeScript project but struggling to find guidance on how ...

Problem with selecting dates in rangepicker

Having trouble with my recursion code for selecting dates in a rangepicker: recurse( () => cy.get('.mantine-DatePicker-yearsListCell').invoke('text'), (n) => { if (!n.includes(year)) { //if year not f ...

Angular Service worker mishandles http redirects (302)

In my current project, I am implementing Angular and Spring Boot technologies. When I build the project, Angular generates the service worker for me. The issue arises when I use an external service (auth2) and my backend redirects to the login page after ...

Combining types: unable to utilize the second optional type within a for loop

I am facing an issue while looping through an array due to the union type. I am wondering what I have overlooked in the code below that is causing Visual Studio Code to not recognize the second optional type for that specific array. class Menu { // name ...

How can I implement a feature in Angular where clicking the edit button loads a form (in a separate component) pre-populated with previous data, along with an update button for

Within the employee-list component, there is a table displaying a list of employees. This table includes an option to edit details. <button type="button" class="btn btn-primary" routerLink="../create-employee">Edit</b ...

Adjusting the selection in the Dropdown Box

I've been attempting to assign a value to the select box as shown below: <dx-select-box [items]="reportingProject" id="ReportingProj" [text]="reportingProject" [readOnly]="true" > ...

Assign a value to ReplaySubject if it is currently devoid of any

I am facing a challenge with my ReplaySubject in the component after content initialization. Whenever it initializes, it always gets set to "/api/bulletin/getall" value and overrides any value assigned to it before in the onViewChanged function. How can ...

The origin of the Angular img src becomes blurred when invoking a function

I want to dynamically change the image src by calling a function that returns the image path. However, when I attempt to do so using the code below, the image element displays as <img src(unknown)/> component.ts: getMedia(row) { this.sharedData ...

Learn how to merge two objects and return the resulting object using TypeScript functions within the Palantir platform

I am looking to generate a pivot table by combining data from two objects using TypeScript functions. My plan is to first join the two objects, create a unified object, and then perform groupBy operations along with aggregate functions like sum and min on ...

How can I update a value using a specific key in Angular?

So, I have a string value that I need to pass to another function. For instance, if the string is 'eng', I want it to be converted to 'en'. I'm looking for a solution that does not involve using slice or if statements. I attempted ...

Ensure that Angular resolver holds off until all images are loaded

Is there a way to make the resolver wait for images from the API before displaying the page in Angular? Currently, it displays the page first and then attempts to retrieve the post images. @Injectable() export class DataResolverService implements Resolv ...

Troubleshooting issue with React and Material UI Table pagination display

Issue with Material UI Table Display When Changing Pages When receiving an array of Artist Objects through props to create a checklist table, I encounter some display issues. The table works fine initially, but when changing pages or sorting, more rows th ...

Guide on implementing Password Confirmation in Angular 7 User Registration

I am currently working on a project that involves creating a user registration form using Angular 7 for the frontend and Laravel 5.8 for the backend. While I have successfully implemented user password confirmation in the backend, I am facing some challeng ...

How to use SASS mixins in Angular 5 components

Within my Angular 5 project, I have organized my SASS styles into a separate directory which contains all the variables, functions, and mixins. These are then imported into my main style.scss file. @import 'abstracts/variables', 'abstracts/ ...

Is it possible to transfer parameters from one page to another page using the pop method in Ionic 2?

Is it possible to pass parameters from one page to another during a push operation, but how can this be done during a pop operation? showfilter(){ this.navCtrl.push(FilterPage,{ fulldetail : this.selectedarea }); } Can you explain how ...