Last active
September 23, 2019 12:31
-
-
Save NicolaasZA/c9daadd3a68611b4cd164493002049b4 to your computer and use it in GitHub Desktop.
Retry SOAP calls until a satisfactory result is returned, or maximum retries are met. NOTE: Still uses deprecated HTTP functionality.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@angular/core'; | |
import { Observable } from 'rxjs'; | |
import { map } from 'rxjs/operators'; | |
import { Http, Headers } from '@angular/http'; | |
export interface ISoapAction { | |
name: string; | |
namespace: string; | |
} | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class SoapService { | |
constructor( public http: Http ) { } | |
public post(serviceUrl: string, authKey: string, action: ISoapAction, params): Observable<any> { | |
const sr = | |
`<?xml version="1.0" encoding="utf-8"?> | |
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | |
xmlns:xsd="http://www.w3.org/2001/XMLSchema" | |
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">` | |
+ (authKey.length === 0 ? `` : this.generateAuthHeader(action.namespace, authKey)) | |
+ `<soap:Body><` + action.name + ` xmlns="` + action.namespace + `">` | |
+ params | |
+ `</` + action.name + `></soap:Body></soap:Envelope>`; | |
const head = new Headers({ 'Content-Type': 'text/xml' }); | |
return this.http.post(serviceUrl + '?op=' + action.name, sr, { headers: head }) | |
.pipe(map((res: any) => { | |
// console.log(res); | |
const dom = new DOMParser().parseFromString(res._body, 'text/xml'); | |
let result = dom.childNodes[0].childNodes[0].childNodes[0].childNodes[0].childNodes[0].nodeValue; | |
if (this.isJson(result)) { | |
result = JSON.parse(result); | |
} | |
// console.log(result); | |
return result; | |
})); | |
} | |
private generateAuthHeader(namespace: string, authKey: string) { | |
if (authKey && authKey.length > 0) { | |
return `<soap:Header><AuthHeader xmlns="` + namespace + `"><AuthKey>` + authKey + `</AuthKey></AuthHeader></soap:Header>`; | |
} | |
return ''; | |
} | |
public isJson(str: string) { | |
try { | |
JSON.parse(str); | |
} catch (e) { | |
return false; | |
} | |
return true; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { SoapService, ISoapAction } from 'soap.service'; | |
@Injectable({ | |
providedIn: 'root' | |
}) | |
export class WSService { | |
constructor(private soap: SoapService) { } | |
private retryMax = 5; | |
private retryDelay = 1000; // Delay between retrying | |
private someAction: ISoapAction = { | |
namespace: 'https://some.domain.com/ws_ServiceName/', | |
name: 'SOAPAction' | |
}; | |
public callSoap(serviceURL: string, serviceKey: string, params) { | |
return new Promise<{ Response: any, ErrorMessage: string }>((resolve, reject) => { | |
let triesCounter = 1; | |
const intervalTimer = setInterval(() => { | |
this.soap | |
.post(serviceURL, serviceKey, this.someAction, params) | |
.subscribe(result => { | |
// Success conditions here in this if statement. | |
if (result.Success) { | |
// When satisfied, call clearInterval to stop the retries, and - | |
clearInterval(intervalTimer); | |
// Call resolve to resolve the promise and let the calling function handle the result. | |
resolve({ | |
Response: result, | |
ErrorMessage: '' | |
}); | |
} else { | |
if (triesCounter >= this.retryMax) { | |
// Maximum retries are met, so we need to stop retrying, and - | |
clearInterval(intervalTimer); | |
// Call reject to pass along the failure to the calling function. | |
reject({ Response: undefined, ErrorMessage: 'No response after ' + triesCounter + ' tries.' }); | |
} else { | |
// Implement the counter and try again. | |
triesCounter += 1; | |
} | |
} | |
}, err => { | |
// Personal choice here on whether to stop trying when an error occurs. | |
// Be sure to increment the retry counter and max checker here if you want to continue. | |
clearInterval(intervalTimer); | |
reject({ Response: undefined, ErrorMessage: err.message }); | |
}); | |
}, this.retryDelay); | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This can work with any http call as well. Essentially, you nest the call inside a setInterval that you stop when you are happy the the response. This is all done inside a promise to send the result back to the caller.