iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 7
1
Modern Web

Angular Firebase 入門與實做系列 第 7

[Angular Firebase 入門與實做] Day-06 Cloud Firestore - Querying Collections-2 offline-data

To improve is to change, to be perfect is to change often.

昨日改進

今天先修正一下昨天的方法,並在collection加入一些欄位metadata、doc的欄位以讓我們在做比較時更容易

req.snapshotChanges().map(actions => {
  return actions.map(a => {
    const data = a.payload.doc.data();
    const doc = a.payload.doc;  // 把doc也保留,這樣我們做資料的比較可以直接使用
    const id = a.payload.doc.id;
    return { id, doc, metadata, ...data };
  });
}) 

在昨天的handler就能直接用doc來做操作,不須特別指定欄位,firebase會依據該doc的那個欄位做比較

  • ts
handler(doc, type) {
  this.query.next(ref => ref.orderBy('updatedAt', 'asc')[type](doc));
}
  • html
<button (click)="handler(message.doc, 'endAt')"> <= </button>

offline-data

離線資料是firebase提供的相當powerful的功能,特別針對手機用戶在連線狀況不穩的時候,當連線異常時他會自動把資料存在cache,並在連線後重新把資料送出,有的這個功能,我們可以輕易地辦到像是line、message等等通訊軟體的送出狀態的功能,也讓使用者在操作上更加便利,與自然,不會因為網路不穩定,讓使用者不斷地重新輸入、發送。

  • 加入offline功能
    只需在app.module.ts的地方將AngularFirestoreModule後面加上enablePersistence()就完成了!
AngularFirestoreModule.enablePersistence(),

這麼簡單!?!?!?沒錯!就是這麼簡單,你現有的所有的code都不需要改!

運作剖析

為了方便觀看,我們將CollectionHandler的get做一下修改

get(config: CloudFirestoreConfig = { isKey: true }): Observable<any> {
  const req = config.queryFn ?
    this._afs.collection(this.url, config.queryFn) : this._fireAction;
  return config.isKey ?
    req.snapshotChanges().map(actions => {
      return actions.map(a => {
        // 我們可以從doc.metadata取得相關的資料
        const metadata = a.payload.doc.metadata;  
        const doc = a.payload.doc; 
        const data = a.payload.doc.data();
        const id = a.payload.doc.id;
        return { id, doc, metadata, ...data };
      });
    }) :
    req.valueChanges();
}
  • matadata 包含兩個狀態,fromCache、hasPendingWrites
屬性 功能
fromCache 是否來自cache
hasPendingWrites 是否等待寫入資料庫

我們在messages-list的地方加上.do方法來觀察資料本身,do方法會在每次next發生時執行,可以放我們想做的事情,並不會影響資料本身,這個做法經常使用在我們想用對得到的資料做其他處理時使用。

import 'rxjs/add/operator/do'; // 記得要import
...
...
...
constructor(private _http: BaseHttpService,....){
  ...
  this.messages$ = this.query.switchMap(queryFn => {
    return this.messagesHandler.get({
      queryFn: queryFn,
      isKey: true
    });
  }).do(d => {
    console.log(d);
  });
  ...
}

打開瀏覽器觀察一下,我們先將所有資料清空,然後新增資料

我們會發現當我們新增一筆資料時,他會回傳兩次next,

hasPendingWrites

第一次的是true,因為他還在等伺服器回應回,所以是true
第二次為false,已經從伺服器回來了,所以是false
我們可以透過這個屬性做到LINE等通訊軟體的已送出送出中的功能

fromCache

兩次都為false,因為這筆資料是我們進入頁面之後才新增的,若是再進入前就已經新增的話會是true。

我們把網路斷線,並且新增一筆資料

會發現他不會回應兩次了,只有第一次的回應,這時候他的hasPendingWrites是true的狀態,我們這時重新整理

我們依然可以看到剛剛新增的資料,但是沒有時間,而且兩個屬性都是true

metadata:{hasPendingWrites: true, fromCache: true}

我們重新連線網路,稍後一下,大概30秒~1分鐘(或是直接重新整理),他會自動重新連線,並回應資料

metadata:{hasPendingWrites: false, fromCache: true}

統整一下我們看到的現象與邏輯,

  1. fromCache指的是當下資料的來源,如果資料是進入頁面後才做的新增、修改,那們他的狀態必定為false
  2. 所以資料都會被存入cache,而離線發送的資料因為不會得到回應,hasPendingWrites狀態為true
  3. 再次進入APP時,所有fromCache狀態必定都是true
  4. 任意一資料的hasPendingWrites為true時,firebase會發送請求給server,並回傳一次next

此功能目前尚在測試階段,不曉得未來會不會加入可以控制的選項,例如部分資料是否要進cache。

offline-data只有在 Chrome, Safari, Firefox瀏覽器有支援這點大家要注意並不是每個瀏覽器都有支援的

本日小節

今天我們再次體會到firebase的強大,只能說科技一直在進化,真的非常的厲害,有機會大家可以去看firebase的sourcecode藉此時做自己的http方法,真的能給使用者煥然一新的使用體驗!

本日範例:https://github.com/ZouYouShun/Angular-firebase-ironman/tree/day6_offline_data

參考文章

https://firebase.google.com/docs/firestore/query-data/query-cursors
https://github.com/angular/angularfire2/blob/master/docs/firestore/offline-data.md
https://firebase.google.com/docs/firestore/manage-data/enable-offline


上一篇
[Angular Firebase 入門與實做] Day-05 Cloud Firestore - Querying Collections
下一篇
[Angular Firebase 入門與實做] Day-07 Cloud Firestore - Hosting
系列文
Angular Firebase 入門與實做31

尚未有邦友留言

立即登入留言