SwiftUI:这可能是 Firestore 中潜在的竞争条件吗?

问题描述 投票:0回答:1

我有两个函数

add(_:completion:)
get(query:completion:)
,我认为这可能会导致我的代码出现错误。由于
add(_:completion:)
Book
实例附加到
@Published books
属性,因此可能会导致侦听器出现竞争条件。这就是我想象的可能发生的方式:

  1. 我使用
    book
    add(_:completion:)
  2. 添加到 Firestore 中的图书集合中
  3. 添加书籍后,监听器就会被触发,同时原始的add(_:completion:)
    函数即将执行它的完成处理程序
  4. 如果
  5. add(_:completion:)
    完成处理程序在
    get(query:completion:)侦听器块之前执行,则不会有问题,因为对侦听器块的后续调用将通过执行
    self.books
    来覆盖
    self.books = books
    属性。但是,如果之前执行过
    get(query:completion:)
    侦听器块,则随后执行
    add(_:completion:)
    完成处理程序将通过执行
    self.books
    将重复的书附加到
    self.books.append(book)
    属性的末尾。
    
    
  6. 我已经用
//<<< Over here!!!

 标记了代码的所有重要部分
class BookRepository: ObservableObject { @Published private(set) var books = [Book]() private var listener: ListenerRegistration? func add(_ book: Book, completion: @escaping (Error?) -> Void) { let _ = try! db.collection(.books).addDocument(from: book) { error in if error == nil { self.books.append(book) } //<<< (1) Over here!!! Might get called at the same time as (2) completion(error) } } func get(query: Query, completion: @escaping (BookError?) -> Void) { // Storing listener to single property so multiple calls to get(query:completion:) won't create multiple listeners listener = query.addSnapshotListener { snapshot, error in var err: BookError? // Make sure no network errors guard error != nil else { completion(.networkError); return } precondition(snapshot != nil, "If there's no error snapshot must exist") // Convert documents to Book instances let documents = snapshot!.documents let books = documents.compactMap { try? $0.data(as: Book.self) } // Check if all documents were successfully decoded and if I didn't try to access an empty collection if documents.count != books.count || documents.isEmpty { err = documents.isEmpty ? .emptyQuery : .incorrectBookData(self.getBadData(documents, books)) // Retrieves ID's of documents which weren't decoded into Books } // Assign books to the @Published property to update UI self.books = books //<<< (2) Over here!!! Might get called at the same time as (1) // Call completion handler completion(err) } } enum BookError: Error { case networkError case emptyQuery case incorrectBookData([String]) } func getBadData(_ docs: [QueryDocumentSnapshot], _ books: [Book]) -> [String] { //... } }

我假设这可能会导致竞争条件是否正确?执行的顺序是什么?

ios swift firebase google-cloud-firestore swiftui
1个回答
1
投票

您可能希望通过确保

add

get
方法永远不会同时执行来解决此问题。您可以为此使用某种操作队列。
    

© www.soinside.com 2019 - 2024. All rights reserved.