Retry the original observable on error after waiting for the second observable in RxJS - TypeScript/Angular 2

Exploring the realms of Angular 2, TypeScript and RxJS is a thrilling journey for me as I delve into creating a basic application that makes use of the Salesforce Ajax Toolkit connections library.

In my quest, I am faced with the challenge of tackling token expiration whenever a method from the connections library is invoked. To address this, I have crafted a service that encapsulates the connections library by employing observables. A prime example can be seen in my customized wrapper function for the insert operation:

 public insert(object: sforce.SObject): Observable<any> {
   return new Observable(observer => {
   // record insertion successful
   let insertSuccess = (result) => {
     observer.next(result);
     observer.complete();
    }

    // error encountered during insertion
    let insertError = (result) => {
      // This part needs refinement
      if (result.faultcode.indexOf('INVALID_SESSION_ID') != -1) {
        this.refreshToken();
      }
      else {
          observer.error(result);
      }
    }

    let callback = { onSuccess: insertSuccess, onFailure: insertError };
    sforce.connection.create([object], callback);
  });
}

Another vital function in my arsenal is one that refreshes the access token:

 public refreshToken(): void {
    this.loginService.login().subscribe(
        response => {

            Globals.SESSION_TOKEN = response.access_token;

            //initialize the salesforce connection 
            this.init(Globals.SESSION_TOKEN, this.loginService.AuthParams.SOAP_URL);
        },
        error => {

        }
    );
}

The crux of my endeavor lies in ensuring that the original insert function waits for the completion of refreshToken. Upon success, I aim to retry the initial insert operation, failing which I intend for the original insert observable to trigger observer.error.

Though I've delved into retry and retryWhen, I find myself grappling with how to orchestrate them effectively to synchronize with the execution of the refreshToken() function. Any insights or suggestions on navigating this challenge would be immensely valued. Many thanks in advance.

Answer №1

In handling errors, the catch operator takes a function that deals with an error and the original source Observable. This allows you to decide whether to resubscribe to the initial source within the catch block:

 public insert(object: sforce.SObject): Observable<any> {
   return new Observable(observer => {
   // successfull inserted the record
   let insertSuccess = (result) => {
     observer.next(result);
     observer.complete();
    }

    // An error occurred while inserting the record
    let insertError = (result) => observer.error(result);


    let callback = { onSuccess: insertSuccess, onFailure: insertError };
    sforce.connection.create([object], callback);
  }).catch((err, source) => {
     if (err.faultcode.indexOf('INVALID_SESSION_ID') != -1) {
        //This waits for the refresh to complete and then resubscribes
        //to the source
        //If the refresh errors then it will skip the resubscribe
        return this.refreshToken().flatMapTo(source);
     }
     //Non-authentication error
     return Observable.throw(err);
  });
}

Next, modify your refreshToken function as shown below:

 public refreshToken(): Observable<any> {
    return this.loginService.login()
      .tap(response => {
        Globals.SESSION_TOKEN = response.access_token;

        //initialize the salesforce connection 
        this.init(Globals.SESSION_TOKEN, this.loginService.AuthParams.SOAP_URL);
      });
}

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

Obtain a controller's reference from a callback by utilizing TypeScript

Implementing a simple controller that utilizes a directive/component and passes a function as binding. However, when the function is called, there is no reference available to access any of the controller class services. Within the "public onTileClicked" ...

'Error: Script ngcc is missing in NPM' - Issue encountered

Out of nowhere, my Visual Studio Code project suddenly began showing two strange errors like this: click to view image All the tags from Angular Material are now being marked as errors, failing to get recognized as valid tags. Attempting to use npm run n ...

Putting Tailwind pruning to the test in a React application using Jest

Is there a way to test Tailwind's pruning using Jest without the need for custom postcss configuration? Can it be done by solely implementing the default webpack config created by CRA 5 (as explained here)? It appears that Tailwind is not applying st ...

When a TypeScript merged declaration composition is used with an extended target class, it fails to work properly

I have a TypeScript problem where I need to combine a class that has been extended with a few others. While searching for solutions, I came across an article outlining a pattern that I thought could be helpful: https://www.typescriptlang.org/docs/handbook ...

Angular template-driven forms with a custom validator allows for creating your own validation

Hey StackOverFlow folks, I'm currently facing an issue with a custom validation in template-driven forms. I have a stepper component and a unique form that encapsulates all the groups. For each step, I need the inputs' sum to be 100%, triggering ...

Rendering basic JSON data from the console to an HTML page using Angular

I have been utilizing openhab for sensor monitoring. To extract/inject the items(things), sensor properties, and room configuration through a web interface, I am making use of openhab's REST queries which can be found here - REST Docs. Wanting to cre ...

Tips for eliminating unnecessary module js calls in Angular 9

https://i.sstatic.net/3R7sr.png Utilizing a lazy loading module has been efficient, but encountering challenges with certain modules like all-access-pass and page not found as shown in the image above. Is there a way to effectively remove unused module J ...

The Array of Objects is not being generated from Action and Effects

I'm attempting to retrieve an array of objects stored in the User model. I've created both an Action and an Effect for this purpose. The structure of the User Model is as follows: export interface User { _id: string, firstName: string, lastName: ...

Displaying a segment of information extracted from a JSON array

I'm currently tackling a project that involves using React, Redux, and TypeScript. Within the JSON file, there is a key-value pair: "data_start": "2022-09-02" Is there a way to display this date in a different format, specifical ...

Encountering difficulties while attempting to transition from angular 9 to angular 10

I attempted to upgrade my Angular project by running the following commands: $ ng update @angular/core@9 @angular/cli@9 $ ng update @angular/core @angular/cli However, when I executed the last command in the console, it resulted in an error message: Your ...

My function won't get called when utilizing Angular

My Angular code is attempting to hide columns of a table using the function shouldHideColumn(). Despite my efforts, I am unable to bind my tags to the <th> and <td> elements. An error keeps popping up saying Can't bind to 'printerColu ...

Avoiding hydration errors when using localStorage with Next.js

Want to save a token and access it using local storage The code snippet I am using is: if (typeof window !== 'undefined') { localStorage.setItem(key, value) } If I remove the window type check, I encounter this error: localStorage is not ...

Is there a way to host an AngularJS 2 application without needing to serve all the files in the `node_modules` directory as well?

Struggling to get the Angular 2 seed application up and running. Upon using npm install, a plethora of files are placed into node_modules that seem excessive for what is necessary to serve alongside the seed application code. Is there a way to only serve ...

Issue with action creator documentation not displaying comments

We are exploring the possibility of integrating redux-toolkit into our application, but I am facing an issue with displaying the documentation comments for our action creators. Here is our old code snippet: const ADD_NAME = 'ADD_NAME'; /** * Se ...

Sharing data among components in Angular 6

I've set up 2 components and a service as outlined below: component-interaction.service.ts @Injectable() export class ComponentInteractionService { public dataSubject = new BehaviorSubject<string>("Test"); getTestData(): Observable<an ...

How to execute a function in a child component that is declared in the parent component using Angular

Is anyone able to help me with an issue I am facing in my Angular project? I have two components, 'app' and 'child'. Within the child component, I have a button that calls a function defined in the app component. However, this setup is ...

tsc and ts-node are disregarding the noImplicitAny setting

In my NodeJS project, I have @types/node, ts-node, and typescript installed as dev dependencies. In the tsconfig.json file, "noImplicitAny": true is set. There are three scripts in the package.json file: "start": "npm run build &am ...

Converting an array of object values to an Interface type in Typescript

In my JSON document, I have an array named dealers that consists of various dealer objects like the examples below: "dealers" : [ { "name" : "BMW Dealer", "country" : "Belgium", "code" : "123" }, { "name" : ...

Angular version 4 is used to retrieve deeply nested JSON data

How do I extract data from a nested JSON file? Here is an example of the JSON structure: { "user1": { "name": "john", "surname": "johnsson" }, "user2": { "name": "Jacob", "surname": "Jacobsson" } } I want t ...

Deleting a NativeScript ImageAsset that was generated using the nativescript-camera module - Easy Steps!

import { takePicture, CameraOptions } from "nativescript-camera"; By setting saveToGallery to false in the CameraOptions, the image captured using takePicture is saved on my Android device in Internal Storage > Android > data > org.nativescript.a ...