メッセージの自動更新
昨日の記事 で、メッセージ一覧の取得を行いました。
一人で書き込んでる分には一見追加したメッセージが一覧に反映されていきますが、これだけでは他のユーザーが登録したメッセージが反映されません。
幸いCloud Firestore in Native modeにはリアルタイムにデータの更新を受け取る機能がありますので、これを使って修正します。
Get realtime updates with Cloud Firestore | Firebase
コード
getMessages関数を下記の様に修正します。
export function getMessages(roomId, email) { // realtime updateする様にしたのでクエリ発行済のルームは再取得しません if (hasMessagesOf(roomId)) { return get(messagesOf(roomId)); } let db = firebase.firestore(); return db.collection("rooms").doc(roomId).collection("messages").where("members", "array-contains", email).orderBy("createdAt") .onSnapshot(function(querySnapshot) { let _messages = []; querySnapshot.forEach(function(msgRef) { let msg = msgRef.data({serverTimestamps: "estimate"}); msg.id = msgRef.id; _messages = [..._messages, msg]; }); // UIに反映(Svelte) messagesOf(roomId).set(_messages); return _messages; }, function(error) { console.log("Error getting messages: ", error); }); }
[QueryのonSnapshot関数]を使用することで、メッセージが追加されたら都度処理が実行されるようになります。
自分が追加した場合も同じく呼び出されるので、メッセージ追加処理で行なっていたUIへの反映処理(Svelte)は削除しました。
// 登録したmessageをUIに追加(Svelte) // realtime update litenerで更新する為コメントアウト //messagesOf(room.id).update(list => list.concat(added));
タイムスタンプで少しハマった
メッセージ追加処理 で、メッセージにサーバー側タイムスタンプを保存する為 firebase.firestore.FieldValue.serverTimestamp()
を設定していましたが、これを利用すると登録直後の更新通知スナップショットにはタイムスタンプがnullで設定されていました。わずかな時間をおいてタイムスタンプが設定されたスナップショットが入ってきましたが、少しタイムラグがある様です。
DocumentSnapshotのdataメソッドにSnapshotOptionsを渡すと挙動を変えることができます。
serverTimestamps: "estimate" | "previous" | "none"
値 | 説明 |
---|---|
estimate | 概算時刻が設定される。最終的に設定される時刻とはズレる |
previous | 更新前の値が設定される |
none | (デフォルト)nullが設定される |
リスナーのデタッチ
本アプリでは一度取得したルームのメッセージをチェックし続けるので、リアルタイム更新リスナーのでタッチ(解除)は行なっていません。
データが不要になったら適切にデタッチしてあげないと、使用リソースが無駄に増え続けてしまいます。
参考 : Detach a listener
var unsubscribe = db.collection("cities") .onSnapshot(function (){ // Respond to data // ... }); // Later ... // Stop listening to changes unsubscribe();
まとめ
これでようやくチャットアプリっぽくなってきました。
リアルタイム更新リスナーは、Cloud DatastoreやCloud Firestore(Datastore mode)にはない機能です。 すごく便利ですね!!
便利すぎて怖くなっているのですが、どの程度気軽に使ってよいものなんでしょうかね(^_^;;
次は検索機能にトライします!
(明日は更新できないかも 🙇)