Ionic – sprawdzanie połączenia z internetem i z serwerem.
Chciałbym wam pokazać coś co wydaje się dość oczywiste, a jednak sporo jest ludzi pyta o to na różnych forach. Mowa o sprawdzaniu w Ionic’u czy urządzenie ma połączenie z internetem oraz czy serwer API odpowiada.
Ja rozwiązałem to w głównym komponencie aplikacji (app.component.ts) w następujący sposób:
import {Component} from '@angular/core'; import {Platform, Events} from 'ionic-angular'; import {StatusBar} from '@ionic-native/status-bar'; import {SplashScreen} from '@ionic-native/splash-screen'; import {HomePage} from '../pages/home/home'; import {OfflinePage} from '../pages/offline/offline'; import {ApiErrorPage} from '../pages/api-error/api-error'; import {Network} from '@ionic-native/network'; import {NetworkProvider} from '../providers/network-provider'; import {ApiService} from "../services/api-service"; @Component({ templateUrl: 'app.html' }) export class MyApp { private mainPage: any = HomePage; private offlinePage: any = OfflinePage; private apiErrorPage: any = ApiErrorPage; public currentPage: any; public apiStatus = null; public online: boolean = true; constructor(platform: Platform, statusBar: StatusBar, splashScreen: SplashScreen, public events: Events, public network: Network, public networkProvider: NetworkProvider, private apiService: ApiService ) { splashScreen.show(); platform.ready().then(() => { statusBar.styleDefault(); splashScreen.hide(); this.initializeApp(); }); } initializeApp() { this.networkProvider.initializeNetworkEvents(); this.checkConnection(); this.events.subscribe('network:offline', () => { this.online = false; this.chooseCurrentPage(); }); this.events.subscribe('network:online', () => { this.online = true; this.checkApi(); }); } checkConnection() { this.online = this.networkProvider.network.type !== 'none'; if (this.online) { this.checkApi(); } else { this.chooseCurrentPage(); } } checkApi() { this.apiService.checkApi( () => { this.apiStatus = true; this.chooseCurrentPage(); }, () => { this.apiStatus = false; this.chooseCurrentPage(); } ); } private chooseCurrentPage() { if (this.online) { if (this.apiStatus !== false) { this.currentPage = this.mainPage; } else { this.currentPage = this.apiErrorPage; } } else { this.currentPage = this.offlinePage; } } }
Jak widać mam pola w klasie które trzymają trzy strony: mainPage, offlinePage, i apiErrorPage. W zależności od statusu połączenia z internetem i z serwerem odpowiednia strona podstawiana jest w polu currentPage.
Zawartość pola currentPage jest podstawiona w jedynej linijce kodu w pliku app.html:
<ion-nav [root]="currentPage"></ion-nav>
Połączenie jest sprawdzane przy uruchomieniu aplikacji oraz przy pomocy obserwowania zdarzeń, którego implementacja opiera się na klasie NetworkProvider, której zawartość pochodzi z tego wątku i wygląda następująco:
import { Injectable } from '@angular/core'; import { Events } from 'ionic-angular'; import { Network } from '@ionic-native/network'; export enum ConnectionStatusEnum { Online, Offline } @Injectable() export class NetworkProvider { private previousStatus; constructor(public network: Network, public eventCtrl: Events) { this.previousStatus = ConnectionStatusEnum.Online; } public initializeNetworkEvents(): void { this.network.onDisconnect().subscribe(() => { if (this.previousStatus === ConnectionStatusEnum.Online) { this.eventCtrl.publish('network:offline'); } this.previousStatus = ConnectionStatusEnum.Offline; }); this.network.onConnect().subscribe(() => { if (this.previousStatus === ConnectionStatusEnum.Offline) { this.eventCtrl.publish('network:online'); } this.previousStatus = ConnectionStatusEnum.Online; }); } }
Z kolei do sprawdzania czy serwer api odpowiada zaimplementowałem prostyendpoint po stronie api, który ma za zadanie jedynie zwrócenie statusu http 200. Natomiast po stronie aplikacji używam metody w serwisie ApiService, które wspomniany endpoint sprawdza. Serwis ten, po usunięciu kodu niezwiązanego z tym artykułem, wygląda tak:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { ConfigService } from './config-service' @Injectable() export class ApiService { private endpointApiTest = '/api/test'; constructor(public http: HttpClient, public config: ConfigService ) { } public checkApi(successCallback, errorCallback) { this.subscribePromise( this.http.get(this.config.apiUrl + this.endpointApiTest), successCallback, errorCallback ); } private subscribePromise(promise, successCallback, errorCallback) { promise.subscribe( (data => { if (typeof successCallback === 'function') { successCallback(data); } }), (error => { if (typeof errorCallback === 'function') { errorCallback(error); } }), ); } }
W moim projekcie pobieram adres url API z serwisu ConfigService, u siebie możecie zrobić to jak wam będzie najwygodniej.
Skomentuj