如何在不创建无限循环的情况下在闭包中使用闭包?

How can I use Closures in Closures, without creating an infinite loop?

这是我的代码

fetchCurrentUser() 函数首先调用 'observeCurrentUserFromDisk',如果它不在磁盘上则调用 'observeCurrentUserToDisk'(firebase),我如何在调用 [=17= 后再次调用 'observeCurrentUserFromDisk' ] 到 return 从 'observeCurrentUserFromDisk' 到第一个使用闭包调用 'observeCurrentUserFromDisk' 的函数(fetchCurrentUser)的结果,试图维护 D.R.Y 谢谢。

func fetchCurrentUser() {
        // I don't want to call these two functions each time
        Api.User.observeCurrentUserFromDisk(onSuccess: { (user) in
            
            self.emailLabel.text = user.email
            
            if let profileUrl = URL(string: user.profileImageUrl!) {
                self.profileImageView.sd_setImage(with: profileUrl)
            }
        }) {
            Api.User.observeCurrentUserToDisk(onSuccess: {
                self.fetchCurrentUser()
            }) { (error) in
                ProgressHUD.showError(error)
            }
        }
    }
func observeCurrentUserToDisk(onSuccess: @escaping () -> Void, onError: @escaping (_ errorMessage: String) -> Void) {
        
        guard let currentUser = Api.User.CURRENT_USER?.uid else { return }
        
        Config.REF_USERS.child(currentUser).observeSingleEvent(of: .value, with: { (snapshot) in
            
            if let dict = snapshot.value as? [String: Any] {
                
                let user = UserModel.transformUser(dict: dict, key: snapshot.key)
                
                Api.Realm.writeUserToDisk(user)
                onSuccess()
            }
        })
    }
    
    func observeCurrentUserFromDisk(onSuccess: @escaping (RealmUser) -> Void, onError: @escaping () -> Void) {
        
        guard let uid = Api.User.CURRENT_USER?.uid else { return }
        let predicate = NSPredicate(format: "id = %@", uid)
        var users: Results<RealmUser>!
        users = usersOnDisk.objects(RealmUser.self).filter(predicate)
        
        if let index = users.index(matching: predicate) {
            let user = users[index]
            
            onSuccess(user)
        } else {
            onError()
        }
    }

您可以在 vars 中捕获您的闭包,然后在另一个闭包中引用它。例如:

var onFetch = { a in print(a) }

var saveUsers = { b in 
    if b {
        onFetch()
    }
}

在其自身内部调用函数没有问题 - 这称为递归,只要您有停止条件,这就不会是无限的。

在您的情况下,您正在确定需要执行的某个地方 observeCurrentUserToDisk - 据推测,如果您不这样做,那么该功能就会完成。那就是你的停止条件。

此外,由于 fetchCurrentUser 是异步的,您将调用它并需要对其结果进行操作,因此向其添加完成(onSuccessonError)处理程序作为嗯。

大致思路如下:

func fetchCurrentUser(onSuccess: @escaping (RealmUser) -> Void, 
                      onError: @escaping (String) -> Void) {

   observeCurrentUserFromDisk(
      onSuccess: onSuccess,
      onError: {
          observeCurrentUserToDisk(
             onSuccess: {
                // start recursive call, and in the next iteration this shouldn't 
                // end in onError of observeCurrentUserFromDisk. 
                // Though, if it's a possibility, you might want to limit
                // the number of tries before failing
                fetchCurrentUser(onSuccess: onSuccess) 
             },
             onError: onError)
      }
}

您可以使用 fetchCurrentUser 的完成处理程序来执行您需要的操作:

fetchCurrentUser(
   onSuccess: { user in
      self.emailLabel.text = user.email
            
      if let profileUrl = URL(string: user.profileImageUrl!) {
         self.profileImageView.sd_setImage(with: profileUrl)
      }
   }, 
   onError: {
      // handle the error case
   })