簡體   English   中英

如何使用 Flutter 防御性地從 Firestore 請求數據

[英]How to request data from Firestore defensively with Flutter

由於 Firestore 是一個 NoSQL 數據庫,沒有嚴格的類型規則和定義的文檔結構,我考慮在我的 Flutter 應用程序中處理損壞的數據。

如果您想知道為什么我要防御性請求,即使它不是第三方 API -> 我可以想到我的應用程序因數據損壞而崩潰的三個原因:

  • 我通過 Firebase 控制台添加了錯誤的數據,例如對本應為number類型的字段使用類型string (重復發生)。
  • 我的應用程序中的錯誤會將損壞的數據添加到 Firestore。
  • 用戶安裝了我的應用程序的舊版本,無法處理新的 Firestore 數據結構。

我的要求:當請求來自 Firestore 的損壞數據時,應用程序不應崩潰,但應報告損壞數據,以便盡快在 Firestore 中修復數據

您如何看待以下方法?

假設我們有一部 model Movie

Movie {
  final String title;
  final int releaseYear;

  Movie({required this.title, required this.releaseYear});

  Movie.from(Map<String, dynamic> data)
      : title = data['title'],
        releaseYear = data['release_year'];
}

命名構造函數from解析來自DocumentSnapshot.data()的文檔數據並返回我們的 model。只要數據具有String類型的字段titleint類型的字段release_year (Firestore 中的number ),這就可以正常工作。

假設實際數據中缺少字段release_year 這會讓請求崩潰。 因此,當前用戶不能對相應的電影做任何事情,作為開發者我也不會注意到,因為它是在用戶的設備上悄悄發生的。

要解決第一個問題,我們可以像這樣對后備數據使用防御性解析: data['release_year']?? -1 data['release_year']?? -1 沒有發生崩潰,但我作為開發人員仍然沒有注意到並且無法修復數據。

為了解決這個問題,我們可以使用 Firebase Crashlytics。 唯一的問題是,如果我們使用防御性解析來防止崩潰,則不會將任何日志發送到 Firebase。這就是我想出這個解決方案的原因:

final snapshot = await FirebaseFirestore.instance.collection('movies').doc('123').get();
try {
  return Movie.from(snapshot.data()!);
} catch (e) {
  await FirebaseCrashlytics.instance
      .recordError(e, e.stackTrace(), reason: 'data of movie ${snapshot.id} is corrupt');
  return Movie.fromCorrupt(snapshot.data()!);
}

首先,應用程序嘗試在沒有任何回退機制的情況下解析文檔數據。 如果數據損壞,則會拋出並捕獲異常。 在 catch 塊中,錯誤被發送到 Firebase,然后調用防御性解析構造函數fromCorrupt讓用戶繼續使用剩余數據在應用程序中。 fromCorrupt ,每個字段都在 null 和類型上進行檢查,然后才用於創建 model Movie 如果值為 null 或類型錯誤,則使用回退值。

你覺得我的方法怎么樣? 我是不是過度工程化了?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM