How to pull data from an HTTP source without relying on promises

Here is a simplified version of the service code I am using:

    Load(Channel: any) {
        // 
        let URL = Globals.AppSiteRoot + Channel.URL
        return this.LoadData(URL)
    }

    Load_Default() {
        let URL = Globals.AppSiteRoot + "dir1/somedata.XML"
        console.log("XYZService.Load_Default------.------>>URL", URL)
        //
        return this.LoadData(URL)
            .then(data => {
                {
                    // do some processing here
                    console.log("XYZService.Load_Default<<P------.------data", data)
                    console.log("XYZService.Load_Default<<P------.------This.Data", this.Data)
                }
            });
    }

    // More information on async/await and Angular can be found at:
    // https://medium.com/@balramchavan/using-async-await-feature-in-angular-587dd56fdc77
    // https://v5.angular.io/api
    // https://v5.angular.io/guide/comparing-observables
    LoadData(URL: string) {

        return new Promise(resolve => {
            this.HttpClient.get(URL)
                .map(res => res)
                .subscribe(
                    data => {
                        console.log("XYZService.LoadData<<P------.------http.get=>data", data)
                        this.Data = data
                        resolve(this.Data)
                    },
                    err => {
                        console.log("XYZService.LoadData<<P------.------http:ERR", err)
                    }
                );
        });
    }

Within an XYZcomponent, I use the following method:

Show(Channel: any) {
        console.log("XYZComponent.Show------.------>>Channel>>" + Channel.URL)
        //
        this.XYZService.Load(Channel)
            .then(data => {
                console.log("XYZComponent.Show------.------>>data", data)  
                this.NavController.parent.select(1);
            });            
    }

You can streamline the component code by utilizing async/await as shown below:

    async ShowV2(Channel: any) {
        console.log("XYZComponent.Show------.------>>Channel>>" + Channel.URL)
        //
        const data = await this.XYZService.Load(Channel)
        console.log("XYZComponent------.------>>data", data)
        // 
        this.NavController.parent.select(1)
    }

If you are confused about whether to use Promises, Observables, or ReplaySubject(1), rest assured that it's a common issue faced by many developers.

Regarding error handling, some recommend avoiding HttpClient.get.subscribe in favor of .toPromise(), but proper error handling is crucial and must not be overlooked.

Async/await syntax may seem cleaner, but keep in mind that Observables still have their own advantages, especially in Angular development.

For your code in .Load() .Load_Default() and the component .Show() methods, consider expecting Observables and implementing them as needed.

Lastly, it's essential to establish clear coding patterns for event emitters like ReplaySubject(1) to avoid confusion when revisiting the code later.

If you're feeling lost in the sea of asynchronous operations, don't worry - simplicity is key, and with time and practice, you'll achieve your goal efficiently.

Please feel free to share any insights or template code with error-handling strategies you find effective in production environments.

npm show ionic version
5.4.16
npm show cordova version
9.0.0
npm show angular version
1.7.9
show @angular/core version
9.0.6
ng --version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 9.0.4
Node: 10.16.0
OS: win32 x64

Angular: 5.0.3
... common, compiler, compiler-cli, core, forms, http
... platform-browser, platform-browser-dynamic
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.4 (cli-only)
@angular-devkit/build-optimizer   0.0.35
@angular-devkit/core              9.0.4 (cli-only)
@angular-devkit/schematics        9.0.4 (cli-only)
@schematics/angular               9.0.4 (cli-only)
@schematics/update                0.900.4 (cli-only)
rxjs                              5.5.2
typescript                        2.8.3
webpack                           3.12.0

Answer №1

To enhance your Angular code, I recommend utilizing Observables instead of Promises as Angular heavily relies on them and promotes a reactive programming style.

Take a look at this sample code snippet:

@Injectable({
  providedIn: 'root'
})
export class SomeService {
  private readonly URL: string = 'someurl';

  constructor(private http: HttpClient) {}

  public loadData(): Observable<any> {
    return this.http.get(this.URL).pipe(
      // To handle errors, you can use the catchError operator
      // Alternatively, consider implementing an HTTP Interceptor for better error handling
      catchError(error => throwError(error)),
      map(res => // perform transformations if necessary),
      tap(res => // add side effects as needed)

     // Avoid subscribing in the service to adhere to best practices
  }
}

You can invoke the method in your component and manually subscribe or utilize the async pipe in the template for automatic subscription management.

Remember to unsubscribe from Observables to prevent memory leaks, although Angular takes care of this automatically for HttpClient instances.

For other Observables, consider using operators like take, first, last, takeUntil, or store subscriptions in properties of type Subscription and unsubscribe in the OnDestroy lifecycle hook (similar practice applies when using takeUntil with a Subject).

If you opt for Promises instead, handle errors with a trycatch block.

I have prepared a stackblitz demo here, which includes an error interceptor implementation.

Ensure to include the interceptor in the providers array of the app module like so:

providers: [{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }],

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

Struggling to make fetch function properly within a NextJs middleware function

I am having trouble with redirecting a user to /login if the authentication token from Laravel is invalid. I am attempting to retrieve the user and, if resp.ok() returns false, delete the invalid "token" cookie and direct the user to /login. However, I con ...

Apollo Client's useQuery function is causing unnecessary refetches when using Next.js' router.push method

Currently, I'm facing an issue where a query within a useQuery Apollo Client hook is being re-run unnecessarily every time Next.js's router.push function is triggered. The problem code snippet looks like this: const Parent = () => { useQuery ...

The specific type of selection return type in Prisma is restricted

My Prisma schema is structured like this: model Sample { id String @id @default(cuid()) createdOn DateTime @default(now()) category String } category should STRICTLY belong to one of these options: const Categories = [ "alphaC ...

Leveraging the power of Chart.js and Ng2-Chart within the Cumulocity platform

I'm currently in the process of developing an Angular application for the Cumulocity IoT platform and I wanted to incorporate custom bar charts using Chart.js. Initially, I faced some challenges with this setup but after some research, I came across n ...

Is it possible to multitask within a structural directive by performing two actions simultaneously?

I want to develop a custom structural directive with the following behavior: <p *myDirective="condition">This is some text</p> If condition is false, the <p> tag will not be displayed at all. If condition is true, the <p> tag wi ...

Ways to set a default selection for an md-radio-button in md-radio-groups

My button group consists of 3 radio buttons for filtering data, and I would like to have a specific button selected by default when the page loads. Below is the code snippet: <md-radio-group ng-model="status" aria-label="filter" ng-model="status" name ...

Arranging Angular Array-like Objects

I am in possession of an item: { "200737212": { "style": { "make": { "id": 200001510, "name": "Jeep", "niceName": "jeep" }, "model": { "id": "Jeep_Cherokee", "name": "Cherokee", "nice ...

Asynchronous requests from clients paired with server-side rendering

Exploring the realm of SEO with Angular4/Node.js has presented a unique challenge for me. Utilizing Angular Universal allows for server-side rendering, enabling me to inject meta keywords, title, and image URLs into the HTML before it reaches the browser. ...

Issue with the drag functionality of Framer Motion carousel causing malfunction

Attempting to create a basic Image Carousel using framer-motion for added functionality. The goal is to incorporate both buttons and drag control for sliding through the images. Currently, it functions properly, but if the slider overshoots on the last im ...

Using custom hooks in JSX triggers a TypeScript error when the returned component is accessed

i just created a custom hook // useDropdown.ts function useDropdown(defaultState: number, options: number[]) { const [state, setState] = useState(defaultState); function Dropdown({ name }: { name: string }) { return ( <> <sel ...

Encountering error in Xcode Archive command when using Ionic Capacitor with React - Command PhaseScriptExecution terminated with a non-zero exit code

After a few days of running the Xcode publishing phase without making any changes to the project, I consistently encounter this error. Oddly enough, when other developers run the code on their computers, they don't face the same issue. Here is the er ...

Using Pipe directive in Angular 2 with ES5: Error - Directive annotation missing from constructor

My simple pipe looks like this: app.DisplayKeystrokePipe = ng.core .Pipe({ name: "displayKeystroke" }) .Class({ transform: function() { } }); On the other hand, I have a more complex component/directive: app.Drop ...

Issue with caching when using lazy loading with Angular 2 components

When naming Angular 2 lazy loaded components, they are designated as 0.js, 1.js, etc. However, the entry point is given a version prefix while all lazy loaded components keep their original names. This leads to discrepancies in the code versions present ...

Is there a way to implement this toolbar in Ionic Angular?

https://i.sstatic.net/sGd1o.png I am looking to replicate the toolbar shown in the image above using Ionic. As a beginner in Ionic development, I am finding it challenging to translate the design into code. I attempted to use a grid layout, but the varyin ...

elimination of nonexistent object

How can I prevent releasing data if two attributes are empty? const fork = [ { from: 'client', msg: null, for: null }, { from: 'client', msg: '2222222222222', for: null }, { from: 'server', msg: 'wqqqqqqqq ...

Highlighting DOM elements that have recently been modified in Angular

Is there a simple way to change the style of an element when a bound property value changes, without storing a dedicated property in the component? The elements I want to highlight are input form elements: <tr field label="Lieu dépôt"> ...

Exploring the world of publishing Angular 2 applications

I recently created an Angular 2 application using npm, but as a beginner I am unsure of some aspects. For instance, when I publish my application, I typically use npm publish to share it on my npm account online. However, I am wondering if there is a way t ...

From the service to the component, navigating the array in Angular

I'm encountering difficulties with Angular Services and I can't seem to pinpoint the issue. Currently, I am working on a book application that utilizes Promises. To enhance performance, I am restructuring my code by implementing service injectio ...

Is it feasible to send a variable to angular.json in order to prevent repetitive code?

I'm searching for a strategy to efficiently pass data to the angular.json file, eliminating the need for redundant build configurations. To illustrate my point better, let's use an example. Currently, in my angular.json file under the configurati ...

The Vuex MutationAction decorator cannot be assigned to a TypedPropertyDescriptor

I am a beginner in Typescript and apologize in advance if this is a rookie mistake. I am struggling to resolve this TS error: @Module({ namespaced: true, name: "Admin" }) class Admin extends VuexModule { public adminUserList: UserList = []; ...