Issue
i have an Ionic application, this application contains set of pages and services, now since i'm working with Ionic & Angular, i decided to build reusable code for different projects.
for example, Http service: in this service i want to centralize the code which manage the communication with server side to achieve the reusable concept and the change will be in one place.
my Http.service code is:
export interface RequestOptions {
observable?: any;
url?:string;
method?: string;
successCallBack?: any;
notSuccessCallBack?: any;
useDefaultNotSuccessCallBack?: boolean;
errorCallBack?: any;
useDefaultErrorCallBack?: boolean;
completeCallBack? : any;
sendToken?: boolean;
data?: any;
refresher?:Refresher;
infinitScroller?: InfiniteScroll;
loader?: Loading;
}
export interface ForkOptions {
requests: RequestOptions[];
useDefaultNotSuccessCallBack?: boolean;
errorCallBack?: any;
useDefaultErrorCallBack?: boolean;
completeCallBack? : any;
refresher?:Refresher;
infinitScroller?: InfiniteScroll;
loader?: Loading;
}
import {Injectable} from "@angular/core";
import {AuthenticationService} from "./authentication.service";
import {Observable} from "rxjs/Observable";
import {HttpClient, HttpHeaders} from "@angular/common/http";
import {AlertController, InfiniteScroll, Loading, Refresher} from "ionic-angular";
import 'rxjs/add/observable/forkJoin';
@Injectable()
export class HttpConnectionService {
constructor(
private http: HttpClient,
private authService: AuthenticationService,
private alertCtrl: AlertController
) {}
/**
* @param {ForkOptions} options: an options which contains the list of requests to be forked together.
* this method will construct an array of observables and handle the response using @responseHandler and @errorHandler methods
* in this service
*/
httpRequests( options: ForkOptions) {
// build the array of observables
let observables = [
...options.requests.map((request) => request.observable)
];
// subscribe to these observables
Observable.forkJoin(observables).subscribe(
(results) => {
// handle the response for each of the requests
for(let i = 0; i < results.length; i++) {
this.responseHandler(results[i], options.requests[i]);
}
}, (error) => {
// handle the errors
this.errorHandler(error, options);
}, () => {
// execute the complete handler
this.completeHandler(options);
}
);
}
/**
* @param {RequestOptions} requestOptions: contains the options and attributes of the request to be constructed
* @returns {any} return a ready to subscribe observable
*/
createObservable(requestOptions: RequestOptions) {
// switch statement to handle the different types of methods.
switch(requestOptions.method) {
// if the case is post or delete method, they would have the same parameters.
case 'post' : case 'delete' :
return this.postDelete(requestOptions);
// if the case is get method, it will be constructed differently
case 'get':
return this.get(requestOptions);
}
}
/**
*
* @param {RequestOptions} requestOptions: the options and attribute of the request (post or delete)
* @returns {any}: return the request observable.
*/
private postDelete(requestOptions: RequestOptions) {
return this.http[requestOptions.method](requestOptions.url, requestOptions.data);
}
/**
*
* @param {RequestOptions} requestOptions
* @returns {Observable<Object>}
*/
private get(requestOptions: RequestOptions) {
return this.http.get(requestOptions.url);
}
/**
*
* @param {RequestOptions} requestOptions identify different attributes of the request.
*/
httpRequest(requestOptions: RequestOptions) {
// send the http request and use the method attribute
// if there is observable sent with request
let observable = requestOptions.observable;
if(observable == undefined){
// if there is no observable, create one
observable = this.createObservable(requestOptions);
}
observable.subscribe(
(response: any) => {
// call the response handler
this.responseHandler(response, requestOptions);
}, (error) => {
// call the error handler
this.errorHandler(error, requestOptions);
}, () => {
// call the complete handler
this.completeHandler(requestOptions);
}
);
}
private responseHandler(response, requestOptions: RequestOptions) {
// if the response success, execute the success call back
if(response.isSuccess) {
requestOptions.successCallBack(response.result);
// check if there is infinit scroller and the response is empty, then disable the infinit scroller
if(requestOptions.infinitScroller && response.result.length == 0) {
requestOptions.infinitScroller.enable(false);
}
}else {
// if the response is not success, check if the notSuccessCallBack is defined,
// if notSuccessCallBack is defined, execute it, other wise, execute the default notSuccess callBacl
if(requestOptions.notSuccessCallBack) {
// execute the provided not success callBack
requestOptions.notSuccessCallBack(response);
}else if(requestOptions.useDefaultNotSuccessCallBack){
// execute the default not success callBack
this.defaultNotSuccessResponse(response);
}
}
}
private errorHandler(error, requestOptions: RequestOptions | ForkOptions) {
// check for the provided error callBack.
if(requestOptions.errorCallBack) {
// execute the provided callBack
requestOptions.errorCallBack(error);
}else if(requestOptions.useDefaultErrorCallBack){
// if u can default error handler
this.defaultErrorHandler(error, requestOptions);
}
}
/**
*
* @param {RequestOptions | ForkOptions} requestOptions: the requests options which contain completeCallBack.
*/
private completeHandler(requestOptions: RequestOptions | ForkOptions) {
// if there is complete callBack, execute it.
if(requestOptions.completeCallBack) {
requestOptions.completeCallBack();
}
// turn off the external components after the response is arrived
// for example: loader, infinit scroller, refreshing
this.turnOffExternalComponents(requestOptions);
}
/**
* contains the default behavioral for the not success response,
* it can be terminated if @useNotSuccessResponse = false in the request options.
* @param response: the response from the server side which contains the error message.
*/
private defaultNotSuccessResponse(response) {
// the default behavioral is to display an error message.
this.alertCtrl.create({
title: "Error!",
subTitle: response.message
}).present();
}
/**
*
* @param error: the error object
* @param {RequestOptions} requestOptions: contains attributes about the request
* used as params to access the external components when turning them off.
*/
private defaultErrorHandler(error, requestOptions: RequestOptions | RequestOptions | ForkOptions) {
// turn off the active components.
this.turnOffExternalComponents(requestOptions);
// create alert for the client.
this.alertCtrl.create({
title: "Error!",
subTitle: error.message
}).present();
}
/**
* terminates the view components which are related to the request,
* @param {RequestOptions | ForkOptions} requestOptions
*/
private turnOffExternalComponents(requestOptions: RequestOptions | ForkOptions) {
// set the refresher to complete
if(requestOptions.refresher) {
requestOptions.refresher.complete();
// after refreshing, enable the infinit scroller.
if (requestOptions.infinitScroller) {
requestOptions.infinitScroller.enable(true);
}
}
// set the infinit Scroller to complete.
// and turn on the infinit scroller.
if(requestOptions.infinitScroller) {
requestOptions.infinitScroller.complete();
}
// check if there is loader, and turn it off.
if(requestOptions.loader) {
requestOptions.loader.dismissAll();
}
}
}
this service will be used by other services in the application to provide http communication with server side.
for now, i don't now if this is a good practice or not.
any guidance or help will be appreciated :)
thanks.
Solution
You could create a component with the infinitscroller in it to wrap your content. Finally your service should expose an API to subscribe to results of http service. Within this component you can subscribe to thoise events and control the scrollerwith data binding. That's the angular pattern.
Something like that:
public errors = new ReplaySubject<any>(1);
public void doRequest(): Observable<any> {
this._http.get('').catch((err, source) => {
this.errors.next(err);
return source;
});
}
in Component:
public ngOnInit() {
this._httpService.errors.subscribe(error => {
this.scrollerEnabled = false;
})
}
Answered By - David Ibl
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.