Observe the Resolved Observable Emitted Within a Promise

I am currently working on creating a customized Angular 2 http request by extending the default functionality, and I am using Ionic 2 local storage to save the authentication token. My main challenge lies in figuring out how to return a resolved promise from my http service so that I can subscribe to the Observable within my component. Despite trying variations like Observable.fromPromise, I have not been successful.

request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {

  // Retrieve the token for this request.
  // * Need to resolve this promise before returning it.
  var promise = this.storage.get('token').then(token => {

    if (typeof url === 'string') { 
      if (!options) {
        // create option object
        options = {headers: new Headers()};
      }
      options.headers.set('Authorization', 'Basic ' + token);
    } else {
      // add the token to the url object
      url.headers.set('Authorization', 'Basic ' + token);
    }

    return super.request(url, options).catch(this.catchAuthError(this));

  }).catch(error => {
    console.log(error);
  });

}

This concept is based on a blog post, but Ionic storage returns a promise instead.

Answer №1

If the storage method returns a promise that is compatible with Rx, then you can implement the solution as shown below:

request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {

    return Observable
        .fromPromise(this.storage.get('token'))
        .flatMap(token => {

            if (typeof url === 'string') {
                if (!options) {
                    options = {headers: new Headers()};
                }
                options.headers.set('Authorization', 'Basic ' + token);
            } else {
                url.headers.set('Authorization', 'Basic ' + token);
            }

            return super.request(url, options).catch(this.catchAuthError(this));

        });
    });

}

If the promise returned by the storage method is not compatible with observables, there is an alternative approach, albeit less elegant:

request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {

    return Observable.create((observer: Observer) => {

        this.storage.get('token').then(token => {

            if (typeof url === 'string') {
                if (!options) {
                    options = {headers: new Headers()};
                }
                options.headers.set('Authorization', 'Basic ' + token);
            } else {
                url.headers.set('Authorization', 'Basic ' + token);
            }

            super.request(url, options).catch(this.catchAuthError(this)).subscribe(result => {
                observer.next(result);
                observer.complete();
            });

        }).catch(error => {
            observer.error(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

Best practices for utilizing React.Provider in Typescript to manage and refresh user context

I'm currently trying to wrap my head around how Typescript is structured. However, my Typescript React web app is failing to build due to the following error: Type '({ user: { id: any; }; } | Dispatch<SetStateAction<{ user: { id: any; }; }& ...

Tips for testing an Angular 6 service with a dependency that utilizes private methods and properties to alter the output of public methods and properties

I've encountered a challenge while attempting to write a Jasmine/Karma test for an Angular 6 app. The test is for a service in my application that relies on another service with private properties and methods, causing my tests to consistently fail. W ...

Issue with Angular 17 button click functionality not functioning as expected

Having trouble with a button that should trigger the function fun(). Here's the code snippet I'm using. In my TS file: fun(): void { this.test = 'You are my hero!'; alert('hello') } Here is the respective HTML: &l ...

The addControl function inside a for loop and async function is not properly assigning a value to the form

My goal is to iterate through an array, make a HTTP request, retrieve another array from it, and assign the selected object from the fetched array to a newly added Form Control in the form. This is how I approached it: for (let i = 0; i < typeaheadFiel ...

Having trouble resolving all parameters for the SiteNotificationComponent: (?)

I encountered an issue while attempting to append a component to the DOM. The error message displayed was "Can't resolve all parameters for SiteNotificationComponent: (?).at syntaxError." My goal was to insert HTML content by invoking showNotificatio ...

"Disable the scroll bar for a specific component in Angular while keeping it visible for the

Is there a way to deactivate the overflow: hidden style for just a single component? The style is defined in my style.scss file as shown below: .Visible-scroll{ overflow: auto } ...

calculate the difference between two dates and then add this difference to a new date

Utilizing TypeScript for date calculations. Example: Initial Date 1: "10/06/2021 10:10:05" Initial Date 2: "08/06/2021 11:10:05" Calculate the difference between the two dates, including date/month/year/hour/min/sec/milliseconds. Ensure compatibility wi ...

What is the reason behind In-memory-web-api not generating an ID?

While I have successfully implemented the GET, PUT, and DELETE methods using InMemoryDbService to simulate an API, I am facing issues with the CREATE method. It seems like the ID is not being generated in the route to display my add form. The error message ...

When `console.log(enum)` is executed in Typescript and AngularJS, the result will be `undefined`

Below is the code snippet for the file that contains the enum: module mops { export enum Status { OK = 0, ROC = (1 << 0), LLA = (1 << 1), LOA = (1 << 2), HIA = (1 &l ...

What is the best way to pass a generic interface to the zustand create function in a TypeScript environment

Having trouble figuring out the right syntax to pass a generic interface when calling a function that accepts a generic type. My goal is to use: const data = itemStore<T>(state => state.data) import { create } from "zustand"; interface ...

What prevents the creation of an Angular app without any content?

Why am I unable to create an empty Angular app? I have been following the guidelines provided on the official documentation: https://angular.io/guide/setup-local. To start off, I installed Angular using the command: npm install -g @angular/cli. Now, whe ...

Is it possible to pass a different variable during the mouse down event when using Konva for 2D drawing?

I am trying to pass an additional value in a mouse event because my handleMouseDown function is located in another file. stage.on('mousedown', handleMouseDown(evt, stage)) Unfortunately, I encountered an error: - Argument of type 'void&apos ...

Error: The AppModule encountered a NullInjectorError with resolve in a R3InjectorError

I encountered a strange error in my Angular project that seems to be related to the App Module. The error message does not provide a specific location in the code where it occurred. The exact error is as follows: ERROR Error: Uncaught (in promise): NullInj ...

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 ...

gulp-angular2 task is malfunctioning

Currently, I am in the process of working on a gulpfile and have written the following task: var tsProject = ts.createProject('app/Resources/public/angular/tsconfig.json'); gulp.task('angular-2', function () { var tsResul ...

Guidance on implementing a Cypress assertion for a JavaScript object retrieved via ag-Grid

Seeking guidance as I navigate the world of UI automation and Cypress, specifically in setting up assertions on JavaScript objects returned by the cypress-ag-grid package Currently, my code is extracting data from ag-grid cy.get("#myGrid").getAg ...

What is the best approach for determining which CSS file to import in next.js?

I'm currently facing the task of selecting which CSS file to apply in my next.js project. I have two separate CSS files, one for desktop and one for mobile devices. My current method of importing CSS files is as follows: // _app.tsx import ".. ...

In Ionic 2, trying to access the IONIC_ENV variable consistently results in it being undefined

Does anyone know how to access the IONIC_ENV variable in order to switch between using the API URL for production and development environments? Every time I try to check it, it returns undefined. process.env.IONIC_ENV I might need to run or add another c ...

The properties defined in the typescript model become inaccessible once the data is transferred to a different webpage

I've created a TypeScript model within my Angular application and initialized an object with that model. However, when passing the object through routing to the second component (UserComponent), the associated types are not available as shown in the i ...

Can I format fixed text alongside a label in an angular material form to match the styling of an input, ensuring they have consistent typography?

I am currently creating a form using Angular material. I want to add static text and a styled label that mimics a form input without interactivity or underlining. By using a custom class, I managed to achieve this effect: <mat-form-field floatLa ...