最近にわかに盛り上がっているのがPWA(Progressive Web App)です。PWAは固有の技術を指すキーワードではなく、モバイルWebアプリを作るためのベストプラクティスと言えます。
今回から何回かに分けて、mBaaSを使ったPWAを作っていきます。今回はTodoの追加、更新、削除をオフライン対応していきます。
localStorageに入ったキューを復元
オフライン時は処理すべき内容をキューに追加します。これは localStorage に保存しておき、再読込時に復元します。
recoverQueue() { let queues = localStorage.getItem('queues'); queues = queues ? JSON.parse(queues) : this.queues; for (const action of ['add', 'done', 'delete']) { if (queues[action].length > 0) queues[action] = this.jsonToClass(queues[action]); } this.queues = queues; },
オンラインになったタイミングで処理実行
オンラインやオフラインになったタイミングは window.addEventListener('online')
や window.addEventListener('offline')
で取得できます。このタイミングでキューにあるデータを処理します。
async watchQueue() { const me = this; window.addEventListener('online', () => { me.message = 'オンライン'; me.executeQueue(); }); window.addEventListener('offline', () => { me.message = 'オフライン'; }); },
処理は追加、更新、削除それぞれに分けて行います。
async executeQueue() { const me = this; if (this.queues.add.length > 0) { this.message = '未処理のデータ追加中…'; await this.addQueue(this.queues.add); } if (this.queues.done.length > 0) { this.message = '未処理のデータ更新中…'; await this.doneQueue(this.queues.done); } if (this.queues.delete.length > 0) { this.message = '未処理のデータ削除中…'; await this.deleteQueue(this.queues.delete); } this.message = 'キューの処理完了'; this.filter(); this.saveQueue(); },
追加処理
追加処理はすでにある this.saveTask
を実行するだけですが、仮で与えている objectId を削除するのを忘れないようにしましょう。
async addQueue(tasks) { for (let i = 0; i < tasks.length; i += 1) { let task = tasks[i]; delete task.objectId; task = await this.saveTask(task) this.queues.add.splice(0, 1); } },
更新処理
更新処理の場合、mBaaSにあるデータ、またはローカルにしかないデータを対象としているという二パターンが考えられます。objectIdがlocal_ではじまる場合はオフラインデータなので、まず保存処理を実行した上で更新を実行します。処理後、タスク一覧のデータを差し替えます。
async doneQueue(tasks) { for (let i = 0; i < tasks.length; i += 1) { let task = tasks[i]; const objectId = task.objectId; if (objectId.match(/^local_.*/)) { delete task.objectId; task = await this.saveTask(task) } task = await task.update(); const index = this.allTasks.findIndex(task => task.objectId == objectId); if (index > -1) { this.allTasks[index] = task; } this.queues.done.splice(0, 1); } },
削除処理
削除処理はオンラインの場合はクラウド上のデータを削除します。ローカルの場合は配列から消して完了です。
async deleteQueue(tasks) { for (let i = 0; i < tasks.length; i += 1) { let task = tasks[i]; const objectId = task.objectId; if (!objectId.match(/^local_.*/)) { task = await task.delete() } const index = this.allTasks.findIndex(task => task.objectId == objectId); if (index > -1) { this.allTasks[index].splice(index, 1); } this.queues.delete.splice(0, 1); } },
まとめ
オフラインだった場合に一時的にキューを記録しておくこと、キューをlocalStorageにも書き出しておくことで再実行時に復元できるようにしています。こうすることで、オフライン時にもデータ操作ができるmBaaS連携アプリが作れました。
ここまでのコードはNCMBMania/PWA-NCMB at v5にアップロードしてあります。実装時の参考にしてください。