4

Good afternoon, I am creating an application in ionic using angular where currently it handles two connection modes: connected if the user has internet access and disconnected if they do not have it

Currently I have a feature and it is that if the user is in connected mode he must call an API otherwise he must make calls to queries in SQLite:

component.example.ts

getUsers () {
  this.dataLayer.getUsers().subscribe (...)
}

data-access-layer.ts

getUsers () {
  if (this.connectionMode == 'online') {
     this.httpcliente.post (...)
  } else {
     this.sqliteclient.query ("...")
  }
}

My question would be what is the best way to implement this strategy, since the way to make conditions to validate if the connection is one or the other does not seem the best to me or maybe use an enumeration

enum AccessDataSqLite {
   getUsers = "...",
   getData = "...",
}

I would appreciate if you can send me references, link or a better way to implement this strategy

Thank you very much

  • 1
    sync databases in background and always query SQLite. –  Oct 17 '20 at 21:24
  • If you plan to give users offline experience, there is some good articles about PWA working offline [Create Offline Web Apps Using Service Workers & PouchDB](https://www.sitepoint.com/offline-web-apps-service-workers-pouchdb/) and [How To Make Your PWA Offline On Demand](https://dev.to/daviddalbusco/how-to-make-your-pwa-offline-on-demand-5dee) – Syntax Oct 19 '20 at 05:56

1 Answers1

5

If you want to build this behavior, you can simply implement the Strategy pattern

Example:

import { Injectable } from "@angular/core";
import { fromEvent, merge } from "rxjs";
import { startWith, map } from "rxjs/operators";

interface Strategy {
  getData1(): any;
  anotherMethod(): any;
}

class SQLStrategy implements Strategy {
  getData1() {
    console.log("SQl", "getData1");
  }

  anotherMethod() {
    console.log("SQl", "anotherMethod");
  }
}

class HTTPStrategy implements Strategy {
  getData1() {
    console.log("HTTP", "getData1");
  }

  anotherMethod() {
    console.log("HTTP", "anotherMethod");
  }
}

@Injectable()
export class DataLayerService {
  private strategy;

  constructor() {
    // init strats
    const sqlStrategy = new SQLStrategy();
    const httpStrategy = new HTTPStrategy();

    merge(fromEvent(window, "online"), fromEvent(window, "offline"))
      .pipe(
        startWith(1),
        map(x => navigator.onLine)
      )
      .subscribe(x => {
        console.log("navigator.onLine", x);
        this.strategy = x ? httpStrategy : sqlStrategy;
      });
  }

  public getData1() {
    this.strategy.getData1();
  }

  public anotherMethod() {
    this.strategy.anotherMethod();
  }
}

Stackblitz: https://stackblitz.com/edit/angular-ivy-fggs4r?file=src/app/data-layer.service.ts

enno.void
  • 6,242
  • 4
  • 25
  • 42
  • It was just what I needed, I will use your concept to build a solution, thanks!!!! – Herman Andres Figueroa Oct 22 '20 at 18:27
  • There are a few issues with this code, but the most glaring is that you don't manage the subscription of the (hot) observable, which will cause a memory leak, even if the service is destroyed. – B Thuy Oct 23 '20 at 22:27
  • @BThuy https://stackoverflow.com/questions/40861494/angular2-unsubscribe-from-http-observable-in-service/40885304#40885304 – enno.void Oct 26 '20 at 08:12
  • @enno.void The answer you have linked is not correct. The way you defined the service above does not automatically make it a singleton. You would have to use the `providedIn: 'root'` in the `@Injectable` decorator. See https://angular.io/guide/singleton-services – B Thuy Oct 26 '20 at 08:23