RxJS wait for second observable then retry original observable on error - TypeScript/Angular 2

人盡茶涼 提交于 2019-12-08 07:26:42

问题


I am fairly new to Angular 2, TypeScript and RxJS and I am creating a simple application that leverages the Salesforce Ajax Toolkit connections library.

I am trying to write a handler to catch when a token has expired any time a method from the connections library is called. I have created a service that essentially wraps the connections library to use observables. For example if we look at the insert function I have created my own wrapper function:

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

    // An error occured inserting the record
    let insertError = (result) => {
      // This does not work yet
      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);
  });
}

I have another function 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 => {

        }
    );
}

I essentially want the original insert function to wait for refreshToken to complete. If it is successful I want to retry the same insert again, otherwise I want the original insert observable to call observer.error.

I've looked into retry and retryWhen, however I haven't been able to figure out how to implement it to wait for the refreshToken() function to complete. Any guidance or advice on this matter would be greatly appreciated. Thank you in advance.


回答1:


The catch operator accepts a function which processes an error and the source Observable. This means that if you catch an error you can determine whether you want to resubscribe to the original source in the catch block:

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

    // An error occured 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);
  });
}

Then make your refreshToken function into something like so:

 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);
      });
}


来源:https://stackoverflow.com/questions/38602186/rxjs-wait-for-second-observable-then-retry-original-observable-on-error-typesc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!