I have the following service code I simplified for posting here
Load(Channel: any) {
//
let URL = Globals.AppSiteRoot + Channel.URL
return this.LoadData(URL)
}
Load_Default() {
let URL = Globals.AppSiteRoot + "dir1/somedata.XML"
console.log("XYZService.Load_Default------.------>>URL", URL)
//
return this.LoadData(URL)
.then(data => {
{
// do some processing here
console.log("XYZService.Load_Default<<P------.------data", data)
console.log("XYZService.Load_Default<<P------.------This.Data", this.Data)
}
});
}
// https://medium.com/@balramchavan/using-async-await-feature-in-angular-587dd56fdc77
// https://v5.angular.io/api
// https://v5.angular.io/guide/comparing-observables
LoadData(URL: string) { // : Observable<any>
return new Promise(resolve => {
// first argument is URL, put config as second argument
// return this.http.get(URL, {responseType: 'text'})
this.HttpClient.get(URL)
.map(res => res)
.subscribe(
data => {
//
console.log("XYZService.LoadData<<P------.------http.get=>data", data)
// Do some processing here, if needed...
this.Data = data
// return new Observable(this.Data);
resolve(this.Data)
}
,
err => {
// https://forum.ionicframework.com/t/handle-errors-with-http-services/53229
console.log("XYZService.LoadData<<P------.------http:ERR", err)
}
);
});
}
In a XYZcomponent I do the following:
Show(Channel: any) {
console.log("XYZComponent.Show------.------>>Channel>>" + Channel.URL)
//
this.XYZService.Load(Channel)
.then(data => {
console.log("XYZComponent.Show------.------>>data", data)
this.NavController.parent.select(1);
});
}
If I switch to using async/await my component code becomes like this, which I must admit that once one accepts await is blocking, the code seems cleaner than the use of Promise .then....
async ShowV2(Channel: any) {
console.log("XYZComponent.Show------.------>>Channel>>" + Channel.URL)
//
const data = await this.XYZService.Load(Channel)
console.log("XYZComponent------.------>>data", data)
//
this.NavController.parent.select(1)
}
I am getting mixed messages from the many posts and blogs I read.
Some say don't use HttpClient.get.subscribe if you expect to only receive data once..., instead use .toPromise() however they never show how to handle errors.
Some say async/await are only sugar syntax still using Promises under the hood.
Some say Observables are much better and even Angular uses them extensively.
Regarding the code in .Load() .Load_Default() and the component .Show() methods are these places to expect an Observables and how to code it as such?
I have used ReplaySubject(1) elsewhere to broadcast events from services and to communicate indirectly from page to page. However, I am not sure this is another place to use it though.
My typical concern with event emitters like ReplaySubject(1), especially when I visit the code some months later,
1) How did I ensure I subscribed to an event only once? where?
2) Did I unsubscribe and where?
BTW, even though I am using Promises, Observables, ReplaySubject(1) it's all Chinese to me and a great source of distraction and frustration to get to my simple goal that of display some data or some pictures I retrieve from the web. Therefor, if you have an approach/pattern to lay down the code clearly such that when I comeback four months from now, it all make sense :)
Please include template code with error handling you would use in production. Thank you for sharing any of your insights.
npm show ionic version
5.4.16
npm show cordova version
9.0.0
npm show angular version
1.7.9
show @angular/core version
9.0.6
ng --version
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 9.0.4
Node: 10.16.0
OS: win32 x64
Angular: 5.0.3
... common, compiler, compiler-cli, core, forms, http
... platform-browser, platform-browser-dynamic
Ivy Workspace: Yes
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.900.4 (cli-only)
@angular-devkit/build-optimizer 0.0.35
@angular-devkit/core 9.0.4 (cli-only)
@angular-devkit/schematics 9.0.4 (cli-only)
@schematics/angular 9.0.4 (cli-only)
@schematics/update 0.900.4 (cli-only)
rxjs 5.5.2
typescript 2.8.3
webpack 3.12.0
I suggest using Observables instead of Promises since Angular use the first a lot and in a way promotes the reactive style.
Consider the following example code:
@Injectable({
providedIn: 'root'
})
export class SomeService {
private readonly URL: string = 'someurl';
constructor(private http: HttpClient) {}
public loadData(): Observable<any> {
return this.http.get(this.URL).pipe(
// if you want to handle errors you can use the catchError operator
// however, a better way is to use a HTTP Interceptor instead
// if you want to see how you can handle errors with the interceptor let me
// know
catchError(error => throwError(error)),
map(res => // do some transformation if you need),
tap(res => // add some side effects if you need)
// don't subscribe in the service - it is considered to be a bad practice
}
}
You can call the method in your component and manually subscribe to it or you can use the async
pipe in the template to subscribe and unsubscribe automatically.
Although it's very important to unsubscribe from observables in to order to avoid memory leaks, Angular manages for you this for the HttpClient so is no need for you to manually unsubscribe.
For all other Observables you can use operators like take
, first
, last
, takeUntil
or store the subscription into a property of type Subscription
and unsubscribe in the OnDestroy life cycle hook (the same must be done in the case of takeUntil
operator where you call next and complete/unsubscribe for its argument which is a Subject
).
If you want to use Promises instead, for handling errors you can use the trycatch
block.
I've created a stackblitz here where I included the error interceptor.
Make sure to provide the interceptor in the providers array from the app module like so:
providers: [{ provide: HTTP_INTERCEPTORS, useClass: ErrorInterceptor, multi: true }],