0

因此,我试图确保在删除用户时以特定顺序执行一组异步任务。

所以我想要发生的是:

  • 检查用户是否在购买时添加了客人
  • 如果用户没有客人或根本没有任何购买,则从函数返回并继续删除过程(要点 6)
  • 如果用户有任何购买的客人,请删除每个客人
  • 删除所有客人后,继续删除他们所做的每笔购买
  • 删除所有购买后,继续将实际用户本身从 Firestore 中删除
  • 2 秒后,我将用户从 firebase 身份验证中删除,以确保尝试删除具有空用户的文档时不会发生崩溃
  • 然后我只是转到主菜单

所以我试图用我的函数中的这段代码来完成这个:

let deleteAction = UIAlertAction(title: "Delete", style: .destructive) { (deletion) in
            let semaphore = DispatchSemaphore(value: 0)
            
            
            self.deleteButton.isHidden = true
            self.loadingToDelete.alpha = 1
            self.loadingToDelete.startAnimating()
            
            DispatchQueue.global(qos: .background).async {
                self.db.collection("student_users/\(user.uid)/events_bought").getDocuments { (querySnapshot, error) in
                    guard error == nil else {
                        print("The docs couldn't be retrieved for deletion.")
                        return
                    }
                    
                    guard querySnapshot?.isEmpty == false else {
                        print("The user being deleted has no events purchased.")
                        return
                    }
                    
                    for document in querySnapshot!.documents {
                        let docID = document.documentID
                        
                        self.db.collection("student_users/\(user.uid)/events_bought/\(docID)/guests").getDocuments { (querySnap, error) in
                            guard querySnap?.isEmpty == false else {
                                print("The user being deleted has no guests with his purchases.")
                                return
                            }
                            
                            for doc in querySnap!.documents {
                                let guest = doc.documentID
                                self.db.document("student_users/\(user.uid)/events_bought/\(docID)/guests/\(guest)").delete { (error) in
                                    guard error == nil else {
                                        print("Error deleting guests while deleting user.")
                                        return
                                    }
                                    print("Guests deleted while deleting user!")
                                    semaphore.signal()
                                }
                                semaphore.wait()
                            }
                        }
                    }
                }
                
                
                self.db.collection("student_users/\(user.uid)/events_bought").getDocuments { (querySnapshot, error) in
                    guard error == nil else {
                        print("There was an error retrieving docs for user deletion.")
                        return
                    }
                    guard querySnapshot?.isEmpty == false else {
                        return
                    }
                    for document in querySnapshot!.documents {
                        let docID = document.documentID
                        
                        self.db.document("student_users/\(user.uid)/events_bought/\(docID)").delete { (err) in
                            guard err == nil else {
                                print("There was an error deleting the the purchased events for the user being deleted.")
                                return
                            }
                            print("Purchases have been deleted for deleted user!")
                            semaphore.signal()
                        }
                        semaphore.wait()
                    }
                    
                }
        
                
                self.db.document("student_users/\(user.uid)").delete(completion: { (error) in
                    
                    guard error == nil else {
                        print("There was an error deleting the user document.")
                        return
                    }
                    print("User doc deleted!")
                    semaphore.signal()
                })
                semaphore.wait()
                
                
            }
            
            DispatchQueue.main.asyncAfter(deadline: .now()+1.5) {
                user.delete(completion: { (error) in
                    guard error == nil else {
                        print("There was an error deleting user from the system.")
                        return
                    }
                    print("User Deleted.")
                })
               
                
            }
        
            self.loadingToDelete.stopAnimating()
            self.performSegue(withIdentifier: Constants.Segues.studentUserDeletedAccount, sender: self)
            
            
        }

在过去的几个小时里,我一直在尝试将DispatchSemaphore()其实现到我的代码中,但它并没有达到我期望的效果。我会阅读网上的文章和示例,DispatchSemaphore()但就我特别想做的事情而言,场景与我的并不完全相同。

当点击触发此警报操作时,不会打印任何内容,并且最终会永远旋转,用户不会从 Firebase 身份验证中删除,并且 Firestore 数据库中仍有剩余数据,如下所示:

错误

我只是想找出在上面的有序列表中对这些异步任务进行排序的最佳方法,并在数据库中没有剩余的用户删除。提前致谢。

4

1 回答 1

0

您应该使用 Firebase Cloud Function 来处理此问题,该函数具有多种响应客户端请求和数据库更改的方式。这确实需要计费并将您的代码迁移到具有节点 v10 的 javascript,由于跨大多数语言的 firebase 方法一致,这相当简单。

Firebase 功能

两种流行的方法是简单地将 firebase 云函数模块导入您的应用程序或通过 https 调用请求,每种方法都有自己的入口点,各有优缺点,值得一读。

从那里,您将立即删除会影响用户的核心文件,然后在继续清理残留文件之前更新客户端的结果。

Firestore 触发器

另一种与潜在滥用一样合理且更易于管理的替代方法是根据文档删除调用触发器,您可以使用它来触发其他文档继续被删除和清理

您可以在下面阅读它们,它可以在两种情况下包含基本相同的逻辑,但此选项不需要庞大的 firebase 函数模块。

https://firebase.google.com/docs/functions/firestore-events#function_triggers

更新:异步

异步方法只是标记为async允许任务在没有阻塞结构的情况下运行的简单函数,这允许在不依赖另一个任务的情况下触发多个任务。但是,要暂停代码以等待完成某些事情,您可以附加await标志

function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

async function asyncCall() {
  console.log('calling');
  const result = await resolveAfter2Seconds();
  console.log(result);
  // expected output: "resolved"
}

asyncCall();

参考:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

更新:承诺

Promise 与异步函数的工作方式相同,并且独立于父函数运行,并且await如果需要,可以标记自身。

const myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('foo');
  }, 300);
});

myPromise
  .then(handleResolvedA, handleRejectedA)
  .then(handleResolvedB, handleRejectedB)
  .then(handleResolvedC, handleRejectedC);

参考:https ://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

于 2021-04-26T00:45:47.433 回答