Skip to content

Instantly share code, notes, and snippets.

@vaibhavgehani
Created January 12, 2021 11:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vaibhavgehani/9d037f3cb216bf25e4c4180ce3cad8d4 to your computer and use it in GitHub Desktop.
Save vaibhavgehani/9d037f3cb216bf25e4c4180ce3cad8d4 to your computer and use it in GitHub Desktop.
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { environment } from '@env/environment';
import { Network } from '@ionic-native/network/ngx';
import { AlertController, Platform } from '@ionic/angular';
import { Storage } from '@ionic/storage';
import { forkJoin, from, Observable, of } from 'rxjs';
import { finalize, switchMap } from 'rxjs/operators';
import { StoredRequest } from '../../models/request';
@Injectable({
providedIn: 'root'
})
export class APIManager {
disconnectSubscription: any;
connectSubscription: any;
networkAlert: HTMLIonAlertElement;
networkStatus = true;
requestSubscriber: any;
mutex = true;
constructor(
private storage: Storage,
private http: HttpClient,
private network: Network,
private platform: Platform,
private alertCtrl: AlertController
) {
this.platform.ready().then(() => {
this.checkInternetConnection();
});
}
async checkInternetConnection() {
this.disconnectSubscription = this.network.onDisconnect().subscribe(async () => {
this.mutex = true;
this.networkAlert = await this.createNetworkAlert('No Internet', false, 'Please Check you internet Connection and try again',{
text: 'Ok.!, Checking',
role: '',
cssClass: 'secondary',
handler: async () => {
this.networkAlert.dismiss();
this.networkAlert = null;
}
});
this.networkAlert.present();
this.networkStatus = false;
});
this.connectSubscription = this.network.onConnect().subscribe(() => {
this.networkStatus = true;
if(this.networkAlert) {
this.networkAlert.dismiss();
this.networkAlert = null;
}
if (this.mutex) {
this.mutex = false;
this.requestSubscriber = this.checkForUnCompleteAPI().subscribe();
}
});
}
checkForUnCompleteAPI(): Observable <any> {
return from(this.storage.get(environment.REQ_STORAGE_KEY)).pipe(
switchMap((storedOperations: any) => {
let storedObj = JSON.parse(storedOperations);
if (storedObj && storedObj.length > 0) {
return this.sendRequests(storedObj).pipe(
finalize(() => {
this.completeAllRequests().then(async () => {
this.requestSubscriber.unsubscribe();
const stored = await this.storage.get(environment.REQ_STORAGE_KEY); // use the db name that you prefer
});
})
);
} else {
return of(false);
}
})
)
}
completeAllRequests(): Promise <any> {
return new Promise((resolve, reject) => {
this.storage.get(environment.REQ_STORAGE_KEY).then((StoredReqs) => {
let storedObj = JSON.parse(StoredReqs);
storedObj.forEach((request) => {
request.completed = true;
});
this.storage.remove(environment.REQ_STORAGE_KEY);
resolve(this.storage.set(environment.REQ_STORAGE_KEY, JSON.stringify(storedObj)));
});
})
}
storeCallAndRespond(method, url, header, data?): Promise <any> {
return new Promise(async (resolve, reject) => {
const action: StoredRequest = {
url: url,
type: method,
data: data ? data : null,
time: new Date().getTime(),
completed: false,
response: null,
header: header,
id: Math.random().toString(36).replace(/[^a-z]+/g, '').substr(0, 5)
};
const Store = await this.storeRequest(action);
await this.repeatRequest(action).then((response) => {
console.log('Response', response);
resolve(response);
})
});
}
async repeatRequest(action) {
return new Promise(async (resolve, reject) => {
let response;
if (!this.networkStatus) {
// No Internet
resolve(action.data);
} else {
// Internet is there
if (action.type === 'GET') {
response = await this.http.request(action.type, action.url, {headers: action.header}).toPromise();
} else {
response = await this.http.request(action.type, action.url, {body: action.data, headers: action.header}).toPromise();
}
this.updateActionObject(action, response);
resolve(response);
}
});
}
storeRequest(action) {
this.storage.get(environment.REQ_STORAGE_KEY).then((storedOperations) => {
let storedObj = JSON.parse(storedOperations);
if (storedObj) {
storedObj.push(action);
} else {
storedObj = [action];
}
return this.storage.set(environment.REQ_STORAGE_KEY, JSON.stringify(storedObj));
});
}
updateActionObject(action, response) {
this.storage.get(environment.REQ_STORAGE_KEY).then((storedOperations) => {
let storedObj = JSON.parse(storedOperations);
storedObj.forEach((call) => {
if (call.id == action.id) {
call.response = response;
call.completed = true;
}
});
this.storage.remove(environment.REQ_STORAGE_KEY);
return this.storage.set(environment.REQ_STORAGE_KEY, JSON.stringify(storedObj));
});
}
sendRequests(operations: StoredRequest[]) {
console.log('Req Called')
let obs = [];
let oneObs;
for (let op of operations) {
if (!op.completed) {
if (op.type === 'GET') {
oneObs = this.http.request(op.type, op.url, {headers: op.header});
} else {
oneObs = this.http.request(op.type, op.url, {body: op.data, headers: op.header});
}
console.log('Array res', oneObs);
obs.push(oneObs);
}
}
return forkJoin(obs);
}
ngOnDestroy() {
this.disconnectSubscription.unsubscribe();
this.connectSubscription.unsubscribe();
}
async createNetworkAlert(header, backdropDismiss, message, buttonOptions1, buttonOptions2?): Promise<HTMLIonAlertElement> {
const alert = await this.alertCtrl.create({
header,
backdropDismiss,
message,
buttons: !buttonOptions2 ? [buttonOptions1] : [buttonOptions1, buttonOptions2]
});
return alert;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment