Tips on how to properly handle Promises in a constructor function

My Angular Service is currently making http requests, but I am looking to retrieve headers for these requests from a Promise. The current setup involves converting the promise to an Observable:

export class SomeService {
  constructor(private http: HttpClient, private auth: AuthenticationService) {}

  getInfo(id: string): Observable<any> {
    return this.auth.getToken().pipe(mergeMap((token: any) => { 
      let httpOptions = {
        headers: new HttpHeaders({
          'Content-Type':  'application/json',
          'Authorization': 'Bearer ' + token
         })
        }
        return this.http.get(`${this.serverURL}/info`, httpOptions);
    }))
  }
}



getToken() {
   return from(this.storage.get(TOKEN_KEY));
}

However, making multiple requests for 20-50 requests is not ideal. I aim to fetch the auth token once and use it for all requests. Additionally, there is another header coming from a Promise that needs to be used in the requests. Therefore, I am exploring ways to retrieve async headers only once, preferably in the constructor. How can I accomplish this in this scenario?

Answer №1

Before diving into code optimization, consider whether it is truly necessary. Optimal performance is typically crucial for frequently executed code segments. If you're only making 20 to 50 requests, it may not be a critical area for optimization (other parts of your application may require more CPU resources).

However, if you are determined to enhance this aspect, fetching the token in the constructor could be a viable solution.

export class SomeService {
    // Storing the observable for future use
    private getTokenObservable: Observable<string>;

    constructor(private http: HttpClient, private auth: AuthenticationService) {
        // Retrieve and store the token observable
        this.getTokenObservable = getToken();
    }

    getInfo(id: string): Observable<any> {
        // Combining the two observables
        return zip(
            // Reusing the stored observable
            this.getTokenObservable,
            // Requesting the last login information
            this.auth.getLastLogin()
        ).pipe(mergeMap((result) => {
            const token = result[0];
            const lastLogin = result[1];

            let httpOptions = {
                headers: new HttpHeaders({
                    'Content-Type': 'application/json',
                    'Authorization': 'Bearer ' + token
                })
            }
            return this.http.get(`${this.serverURL}/info`, httpOptions);
        }))
    }
}

getToken() {
    return from(this.storage.get(TOKEN_KEY));
}

This approach allows multiple subscriptions to the same observable. Therefore, the token observable is fetched and stored only once, and then reused for subsequent requests.

Furthermore, observe the usage of the zip operator from rxjs. This operator merges two observables, enabling the handling of results from both observables within a single function.

Answer №2

To optimize token retrieval, consider creating a dedicated service solely for getting the token. By storing the token value in a service variable, subsequent requests for the token can bypass unnecessary HTTP calls and quickly provide the token to the requester.

Answer №3

protected _tokenStream = new BehaviorSubject<string>(null);
constructor(...) {
    this.auth.getToken().subscribe(token => this._tokenStream.next(token))
}

fetchData(...) {
this._tokenStream.pipe(
    switchMap(token => // rest remains the same
)

Alternatively, you can create a getter method like below

get tokenStream() {
    return this._tokenStream.pipe(filter(value => !!value))
}

In this scenario, only non-null values will be returned, but if a token is not provided, the process will get stuck.

Answer №4

To simplify matters, you have the option to develop a utility function in a separate file that can be imported into various parts of your code where this token is needed. Alternatively, if the token is retrieved from a server call, you could create a service to handle it and then inject it wherever necessary.

Another approach is to store this token in a constants file and import it whenever it is needed.

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

Is there a way to trigger a JavaScript function once AJAX finishes loading content?

I've been utilizing some code for implementing infinite scrolling on a Tumblr blog through AJAX, and it's been performing well except for the loading of specific Flash content. The script for the infinite scroll can be found here. To address the ...

Generating modal pages on the fly

One thing that's been on my mind is creating modals for my page. Typically, I would include the HTML code for my modal directly in the page like this: <div class="my-modal"> <form action="/home/index"> <input type="text" class="txt- ...

NodeJS - The function app.listen is not defined in this context

I've come across a similar question before, but the answers provided didn't help me resolve my issue. The error message I'm getting is "TypeError: app.listen is not a function"; Here's my full code below. Thank you in advance for your ...

Error message: React Native encountered a prop type failure when an invalid prop of type array was passed to the Overlay component

I am brand new to React Native and encountering an error message when opening a specific component. Although it doesn't hinder navigation, I would like to resolve this issue. I suspect it could be related to a syntax or typo error, but pinpointing the ...

Using the Backbone.js library to make secure requests over https

Currently, I am developing a single page application that involves using Backbone.js and Marionette on the front end, combined with Django and Tastypie on the back end. Recently, I successfully implemented an SSL certificate on the web server and configure ...

Using caret range and package-lock.json to acquire the most recent non-disruptive versions

I understand the purpose of package-lock.json, but I'm unsure about how the caret range works after adding this file. Let's say I have a package called my-module and I want to automatically receive all new non-breaking versions without manually ...

A guide on utilizing the javascript function to toggle the checkbox in each row of a gridview

I am looking to implement a function that checks checkboxes row by row based on specific conditions. The first condition requires an alert popup if three checkboxes are selected in the same row consecutively ("You can't select continuous three hou ...

Is there a way to resolve the execution order dependency of JS-CF using a server-side callback function?

Is there a way to display a form as a pop-up window, with input fields and a submit button, and then retrieve the user's selection from the session? The challenge lies in integrating JS code for the pop-up window with CF server-side code, leading to t ...

A 403 error is thrown by the Microsoft Graph API when attempting to delete the authentication method known as "Microsoft Authenticator"

I'm trying to remove a user's Microsoft Authenticator Authentication Method (#microsoft.graph.microsoftAuthenticatorAuthenticationMethod) from their list of authentication methods, but I keep getting a 403 Forbidden error. Below is the code snip ...

Authenticate through Twitter when using PhoneGap Cordova

Looking to implement Twitter login in my application using JavaScript and HTML. How can I redirect users to the Twitter login page when they click on the "Sign In with Twitter" button? ...

Jquery Timer that can be toggled on and off with a single button

I'm really struggling to find a way to make this work smoothly without any bugs. The button in the code below is supposed to perform three actions: Initiate a countdown when clicked (working) Stop the countdown automatically and reset itself when it ...

Show an error message in a popup window, following a validation error in Laravel

I am facing an issue with displaying error messages in the update modal form. I am using Laravel request for validation and AJAX to submit the form inside a modal. My goal is to show the error message for each field that is inputted incorrectly. However, i ...

Passing values from a Laravel controller to a Vue component as a prop

At the moment, I have a Laravel route that directs to the index function of my controller with an ID passed, where I then return the ID in a view. public function index($id) { return view('progress') ->with('identifier', ...

Issue with running the Jquery each function within a textbox inside an ASP.NET gridview

Below is the gridview markup: <asp:GridView ID="gvDoctorVisits" runat="server" DataKeyNames="AdmissionId" class="tableStyle" AutoGenerateColumns="False" Width="100%" EmptyDataText=& ...

Creating an overloaded callable interface using TypeScript

The thread on implementing a callable interface provides some helpful information, but it doesn't fully address my specific query. interface lol { (a: number): (b: number) => string // (a: string): (b: string) => string // overloaded wi ...

What is the proper way to utilize RxJS to append a new property to every object within an array that is returned as an Observable?

I'm not very familiar with RxJS and I have a question. In an Angular service class, there is a method that retrieves data from Firebase Firestore database: async getAllEmployees() { return <Observable<User[]>> this.firestore.collectio ...

Refreshing Angular 2 + Firebase app causes user to be logged out

Just diving into Angular2, Firebase, and SPAs for the first time. I've been tasked with enhancing a Angular2 (with Firebase email&pw auth) application by adding some new features. The app primarily consists of a blog (main page), a shop (/shop), a ...

Evaluating the parser for oauth2 implicit grant access_token using javascript

I am currently developing an Angular application that utilizes the implicit grant oauth strategy. In case I do not have a valid access token in my cookies, I am redirected to the web interface of the authentication server where I input my credentials and t ...

Angular4: The dragstart event is being triggered as a result of the mousedown event

My div contains a mousedown event for the parent element and a dragstart event specific to that div. However, I am facing an issue where the dragstart event is not being triggered when I try to drag the div. I attempted to use event.stoppropagation() with ...

Is it possible to make the mat-menu-item the same size as the mat-menu button in Angular Material v.12?

How can I ensure that the mat-menu-item button is the same size as the mat-menu itself? For example, click here <div class="container d-block d-md-none"> <div class="row"> <div class="col d-flex justify-content-cent ...