【问题标题】:Passing data to synchronous call in async function在异步函数中将数据传递给同步调用
【发布时间】:2020-01-03 19:09:15
【问题描述】:

我正在使用 firebase,我有一个函数可以从文档引用中返回一个承诺。

func getCatalogItem(ref: DocumentReference) -> Promise<Catalog> {
        return Promise { seal in
        ref.getDocument() { result, err in
            if err != nil {
                seal.reject(err!)
            } else {
                let data = FirestoreDecoder()
                do {
                    let item = try data.decode(Catalog.self, from: result!.data()!)
                    seal.fulfill(item)
                } catch {
                print("Error")
                }
            }
        }
    }
}

它工作正常,但唯一的问题是返回类型是我从文档引用调用中解码的自定义类型,但调用本身是同步的,它使我的应用程序崩溃并出现 nil 错误,因为数据实际上还没有.

这是产生错误的行和函数(nil)

let item = try data.decode(Catalog.self, from: result!.data()!)

我尝试使用 firebase 函数的处理程序创建另一个函数并将该值传递给解码器,但它也返回 nil,并且(我正在使用 awaitkit/promisekit)我尝试搞乱 async/await 但不能让它发挥作用。我该如何解决这个问题?

我的数据库中文档的屏幕截图:

然后我有这个:

let featureditem = Firestore.firestore().collection("catalog").document("TDS faded jeans")
self.featureditem.getDocument() { doc, err in
                            if doc == doc {
                                let item = try! FirestoreDecoder().decode(Catalog.self, from: doc!.data()!)
                                print("\(item)")

这也给了我零。

【问题讨论】:

  • 我建议你避免使用强制展开运算符(!)。尤其是避免在一条线上多次使用,这使得很难弄清楚是什么失败了。所以,首先解开result(例如guard let result = result else { print("result was nil"); seal.reject(...); return }。然后使用相同的模式解开data()返回的任何内容。然后查看您的解码器返回的内容(我将其从data重命名为decoder以避免混淆),如果它走得那么远。
  • 不相关,但您可能希望在您的catch 语句中使用reject,例如seal.reject(error)。如果你要去print 任何东西,我可能会打印实际错误,而不仅仅是字符串文字"Error"
  • 好的,我一定会回去做那些我更担心为什么我不应该这样做的时候得到 nil 的事情,但你的权利也许对我的调试有帮助
  • 啊,我发现问题出在我的编码键中,但是当我强制打开它时它没有引发错误。谢谢@Rob

标签: swift asynchronous google-cloud-firestore swiftui


【解决方案1】:

您需要检查data() 是否可以返回 nil,因为这是在没有找到文档时返回的内容。根据链接的 API 文档:

检索文档中的所有字段作为 NSDictionary。如果文档不存在,则返回 nil

要么,要么在假设有数据之前检查exists

【讨论】:

  • 我排除了这一点,因为我知道数据存在并且它(应该)总是存在,但我去检查了,由于某种原因,我的文档返回 nil,即使我可以在 firestore 中清楚地看到它并且我已检查错别字
  • 因为我自己看不到,所以我很怀疑。 Firestore SDK 不会弄错这些东西。请编辑代码以在每个步骤中检查 nil,而不是盲目地假设不是 nil。还包括一个屏幕截图,以便我们看到自己。
  • FWIW,我建议不要先检查是否存在。我怀疑你补充说是为了完善你的答案,但作为一般规则,执行读取操作并处理失败几乎总是更好,而不是先检查存在。
  • @Rob 我这里指的存在检查是从快照本身直接指示快照是否有任何数据。如果数据不为零,则它应该始终为真。这不是异步查询。
  • 我不担心异步/同步行为。只是作为一般规则,执行“尝试并处理失败”几乎总是比“检查存在然后尝试打开”模式更好。 1、效率更高; 2. 它解决了多线程环境中的竞争条件(诚然,这里不太可能成为问题)。但如果这些 cmets/observations 打扰到你,我很乐意删除...
【解决方案2】:

我尝试访问的特定文档将返回 nil 值但尝试使用另一个文档解决问题的异常错误,这可能是因为我将字段命名错误并最终删除它并使用正确的名字,但没有办法真正知道。

【讨论】:

  • 我的编码键确实发生了错误,但这不是根本问题
猜你喜欢
  • 2015-12-01
  • 2020-08-03
  • 2021-12-29
  • 2012-07-25
  • 1970-01-01
  • 1970-01-01
  • 2013-07-12
  • 2020-04-22
  • 1970-01-01
相关资源
最近更新 更多