Make your angular ionic app offline runnable using Ionic Storage
You might be aware that we can make web application offline runnable using service woker. But service worker doesn't work with Ionic hybrid mobile apps as those are blocked webview. Obvious another solution in such case is to use Ionic Storage to cache all required data and then use it as required.
After digging deep I realized that I only need to cache the responses of HTTP GET request in my case, as assets and other static stuffs are already served by cordova wether its offline or online mode.
So I wrote a custome injectable service which internally uses HttpClient. This implementaion is kind of wrapper for HttpClient class. All I deed is wrote a get() method in a service which is capable of checking network connectivity and based on that make a dicision whether to return cached response or make a actual HTTP GET call using HttpClient, cache the response and then return it back. Instead of directly using HttpClient, I'm using this new service to make GET calls.
Below is simple implementation of service:
import { HttpClient, HttpResponse } from '@angular/common/http';import {Injectable} from '@angular/core';import {Observable, throwError} from 'rxjs';import {Network} from '@ionic-native/network/ngx';import {catchError, map} from 'rxjs/operators';import {Storage} from '@ionic/storage';import {Platform} from '@ionic/angular'; @Injectable({ providedIn: 'root'}) export class CustomHttpService{ private isConnected: boolean; constructor(private storage: Storage, private network: Network, private httpClient: HttpClient, private platform: Platform) { let disconnectSubscription = this.network.onDisconnect().subscribe(() => { this.isConnected = false; /*this.sharedService.showToast('You are offline.', 'danger').then();*/ }); let connectSubscription = this.network.onConnect().subscribe(() => { /*this.sharedService.showToast('You are online.', 'dark').then();*/ this.isConnected = true; }); } get(url: string, options?: any): Observable<any> { if(this.platform.is('cordova')) { if(this.isConnected) { return this.httpClient.get(url, options).pipe((map((data) => { this.storage.set(url,data).then(); return data; })), catchError((err) => { return throwError(err); })); } else { return new Observable ((observe) => { this.storage.get(url).then((data) => { return observe.next(data) ; }, (err) => { return throwError(err); }); }); } } else { return this.httpClient.get(url, options); } }; }
We can also do the same for other types HTTP requests such as POST, PUT, DELETE etc. In that case we might need to create a pipeline/queue of requests. Once app is online we can start triggering them in sequence. But things can get worse if application involves stuff like transactions. For such cases CouchDb and PouchDb are best suitable as it uses special sync protocol.
Comments
Post a Comment