Даже в сегодняшнем мире гиперподключений будет много случаев, когда людям придется отключать данные для экономии заряда батареи или просто терять мобильную связь во время путешествий. Нет ничего более неприятного для мобильных пользователей, когда они теряют соединение с приложением, как только они приближаются к зоне со слабой / отсутствующей сетью. Как разработчики приложений, мы ничего не можем сделать с сетевыми системами или аккумуляторами смартфонов, но у нас есть контроль над тем, как мы доставляем наши продукты офлайн-приложениям.

Что такое "сначала офлайн"?

Автономный подход к разработке приложений становится все более популярным - логика здесь в том, что ваше приложение будет работать прекрасно все время, будь то онлайн или офлайн - данные загружаются на устройство пользователя и могут быть доступны без активного интернет-соединение.

Недавно я разрабатывал инструмент CRM (управление взаимоотношениями с клиентами), и у меня возникла потребность в автономных возможностях.

Проблемы, с которыми я столкнулся:

Я использую Ionic для разработки гибридного мобильного приложения. Ionic предоставляет собственный плагин, «Ionic Native Storage», который в основном использует локальное хранилище устройства для локального сохранения данных. Он отлично работал в среде разработки, я использовал OnePlus 6 для тестирования приложения. После развертывания в производственной среде я начал сталкиваться с миллиардами кошмаров.

По сути, происходит то, что телефоны Android низкого уровня очищают кэш и данные локального хранилища приложений, чтобы сэкономить память, что приводит к потере всех данных, хранящихся в локальном хранилище. Немногие пользователи столкнулись с проблемой, поскольку они использовали такие приложения, как C Cleaner, Clean Master и т. Д., Для очистки кеш-памяти. Возможно, я ошибаюсь в этом предположении об основной причине проблемы, но именно это я обнаружил после тестирования приложения в нескольких условиях.

Кроме того, сохранение больших массивов JSON в локальном хранилище и извлечение их оттуда заставляют приложение вести себя странно и временами зависать в обработке.

Это сделало приложение неработоспособным, если говорить об автономных возможностях.

Временное исправление

Мне кое-как удалось заставить приложение работать, используя некоторые хаки, например:
1. Хранение очень простых и строго только необходимых данных.
2. Периодическая программная самоочистка хранилища.
3 • Попросить пользователя очистить свое хранилище вручную, перейдя в диспетчер приложений телефона и очищая данные каждый день.

Решение (пока):

Я отчаянно искал окончательное решение. У меня есть два варианта: i. SQLite, ii. СумкаDB-CouchDB

Не знаю почему, но я обнаружил, что SQLite немного «ох»… Разочаровывает / раздражает.
Я решил использовать PouchDB-CouchDB для решения проблемы.

Что такое PouchDB?
PouchDB - это API базы данных в браузере с открытым исходным кодом, написанный на JavaScript. Он создан по образцу CouchDB - базы данных NoSQL, на которой работает npm. Используя этот API, мы можем создавать приложения, которые работают в офлайн и онлайн. PouchDB внутренне использует WebSQL и IndexedDB для хранения данных.

Их слоган: База данных, которая синхронизируется!

И это было именно то, что мне было нужно. Затем PouchDB автоматически синхронизирует данные с Apache CouchDB, который снова является базой данных NoSQL.
Что такое CouchDB?
CouchDB обеспечивает беспрепятственный обмен данными между серверами. кластеры к мобильным телефонам и веб-браузерам, обеспечивая удобство использования в первую очередь в автономном режиме, сохраняя при этом высокую производительность и надежность.

Реализовать это было очень просто. Я объясню это на коротком и простом примере. У меня есть модуль в приложении, где я отслеживаю каждое действие пользователя в приложении.

Для этого сначала загрузите CouchDB с его официального сайта. Установите его и нажмите URL-адрес в своем браузере.

http://127.0.0.1:5984/_utils/

Откроется интерфейс под названием Futon. Это встроенный интерфейс CouchDB.

Далее вам нужно создать свою базу данных. Это очень просто, просто нажмите Создать базу данных, дайте имя по вашему выбору и вуаля !.

Данные, хранящиеся в CouchDB, называются документами. _id - уникальный идентификатор каждого документа. Вы можете назначить свой собственный _id или оставить его на couchDB, чтобы генерировать уникальный хеш для каждого документа.
Чтобы узнать больше, посетите официальную документацию CouchDB.

Теперь, когда у нас есть CouchDB, я надеюсь, что ваше приложение Ionic готово и ожидает перехода в автономный режим. (Чтобы узнать об Ionic, посетите Ionic Framework).

Чтобы установить PouchBD в ваше приложение Ionic:

npm install pouchdb --save

Если вы используете TypeScript, также установите

npm install @types/pouchdb --save --save-exact

Создайте поставщика и добавьте его в файл app.module.

import { ActivityTracker } from '../providers/activity-tracker';

и экспортируем под провайдером. Ваш файл app.module будет выглядеть примерно так

import { NgModule, ErrorHandler } from '@angular/core';
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';
import { ActivityTracker } from '../providers/activity-tracker';

@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [{provide: ErrorHandler, useClass: IonicErrorHandler}, Todos]
})
export class AppModule {}

При попытке подключиться к CouchDB вы можете столкнуться с проблемой CORS (совместное использование ресурсов между источниками).

Не о чем беспокоиться. Просто выполните следующие шаги:

npm install -g add-cors-to-couchdb
Then run:
add-cors-to-couchdb

Теперь запачкаем руки. Добавьте следующий код в свой провайдер:

import { Injectable } from '@angular/core';
import PouchDB from 'pouchdb';

@Injectable()
export class ActivityTracker {
  data: any;
  db: any;
  remote: any;
constructor() {
    this.db = new PouchDB('crm_activitytracker');
    this.remote = 'http://localhost:5984/crm_activitytracker';
    
    //To know more about options, visit pouchdb.com
    let options = {
      live: true,
      retry: true,
      continuous: true,
      auto_compaction: true
    };
    this.db.sync(this.remote, options);
  }
  saveActivity(data) {
    data.activityDateTime = moment().format();
    data.activity ='Dashboard';
    data._id = (moment().unix()).toString();
    this.db.put(data).then((resp) => {
      console.log(resp);
      return resp;
    })
     .catch((e) => {
       console.log(e);
       return e;
     });
   }
}

Вот и все. ДА !! Действительно, вот оно. Вы можете узнать обо всех функциях PouchDB из его документации.

Бонусный совет:

Если вы уже создали документ с _id и хотите обновить его или добавить недостающие поля позже или после некоторых операций, использование этого приведет к ошибке: 409, «Конфликт». Поскольку тот же _id уже связан с документом.

Для этого есть отличное дополнение: «Upsert» («Обновить» или «Вставить»).
Это вам очень поможет.

Чтобы установить PouchDB Upsert

npm install pouchdb-upsert

Импортируйте это в своего провайдера

import PouchDB from 'pouchdb';
PouchDB.plugin(require('pouchdb-upsert'));

Теперь наш Провайдер будет выглядеть так:

import { Injectable } from '@angular/core';
import PouchDB from 'pouchdb';
PouchDB.plugin(require('pouchdb-upsert'));
@Injectable()
export class ActivityTracker {
  data: any;
  db: any;
  remote: any;
constructor() {
    this.db = new PouchDB('crm_activitytracker');
    this.remote = 'http://localhost:5984/crm_activitytracker';
    
    //To know more about options, visit pouchdb.com
    let options = {
      live: true,
      retry: true,
      continuous: true,
      auto_compaction: true
    };
    this.db.sync(this.remote, options);
  }
saveActivity(data) {
    data._id = (moment().unix()).toString();
    this.db.upsert(data._id, function (doc) {
      if(!doc.count){
        doc.count = 0;
      }
      doc.activityDateTime = moment().format();
      doc.activity ='Dashboard';
      return doc;
      console.log(resp);
    }).then((resp) => {
      console.log(resp);
    // success, res is {rev: '1-xxx', updated: true, id: 'myDocId'}
    })
     .catch((e) => {
       console.log(e);
       return e;
     });
   }
}

doc.count будет вести подсчет количества повторных попыток. Он будет пытаться бесконечно, если документ не будет обновлен.

Перейдите на страницу PouchDB-Upsert, чтобы узнать подробнее об этом плагине.

Итак, это все о том, как я решил проблему и сделал приложение способным работать в автономном режиме. PouchDB автоматически синхронизируется с CouchDB при наличии подключения к Интернету. Таким образом, буквально вам не нужно ничего делать для синхронизации данных между локальным устройством и удаленным CouchDB.

P.S .: Если у вас есть какие-либо предложения или вы обнаружите ошибку в приведенном выше примере, не стесняйтесь связаться со мной. Вы можете связаться со мной по электронной почте: [email protected].

Кредиты:
- Джош Морони:
Мое электронное руководство, когда я застрял в использовании Ionic. В основном, когда я переходил с Ionic v3 на Ionic v4.