Enforcing Async Actions in Firebase

I need to run concurrent Firebase queries in swift. How can I make sure that the completed cycle is completed before it is allowed to start working in my application?

For example, the first query is simple and just pulls data. but the second one iterates through an array looking for a specific node in my firebase database, scrolling through the self.contacts array:

  // First check if friend, and remove/add to friendsURL.observeSingleEventOfType(.Value, withBlock: { snapshot in for oneSnapshot in snapshot.children { for oneContact in contactsArray { for oneContactPhoneNum in oneContact.phoneNumbers { let phoneNumber = oneContactPhoneNum.value as! CNPhoneNumber contactNumber = phoneNumber.stringValue // Clean the number let stringArray = contactNumber!.componentsSeparatedByCharactersInSet( NSCharacterSet.decimalDigitCharacterSet().invertedSet) let newString = "1" + stringArray.joinWithSeparator("") let firebaseFriendNumber = oneSnapshot.value["phoneNumber"] as! String if newString == firebaseFriendNumber { self.friends.append(Friend(userName: oneSnapshot.value["userName"] as! String,phoneNumber: firebaseFriendNumber, status: 2, name: oneContact.givenName, userID: oneSnapshot.key)) // Remove that contact self.contacts.removeObject(oneContact) } } } } // Now do the users search: for oneContact in self.contacts { for oneContactNumer in oneContact.phoneNumbers { let phoneNumber = oneContactNumer.value as! CNPhoneNumber contactNumber = phoneNumber.stringValue let stringArray = contactNumber!.componentsSeparatedByCharactersInSet( NSCharacterSet.decimalDigitCharacterSet().invertedSet) let newString = "1" + stringArray.joinWithSeparator("") let usersURL: Firebase! = Firebase(url: firebaseMainURL + "presentUserIDUserNameByPhoneNumber/" + newString) // Check db: usersURL.observeSingleEventOfType(.Value, withBlock: { snapshot in if snapshot.childrenCount > 1 { // They are users (but not your friends): self.friends.append(Friend(userName: snapshot.value["userName"] as! String, phoneNumber: snapshot.key, status: 1, name: "test", userID: snapshot.value["userID"] as! String)) let userName = snapshot.value["userName"] as! String print("Friends name: " + userName) // Remove that contact self.contacts.removeObject(oneContact) } }) } } }) 

How to check and check whether the second one has ended on usersURL before allowing other actions in the application?

+2
source share
1 answer

One approach to terminating an asynchronous function signal is to use a termination handler. You have already used completion handlers in the Firebase API, and there are many APIs in the system framework, so I won’t explain this further.

Given this approach, wrap your code in a function, say updateContacts , using a completion handler. Typically, an asynchronous function returns a calculated value or an error. In some cases, it simply succeeds or fails - without returning a value. You express this in the signature of the completion handler. Your updateContacts function may not calculate the value, but in any case, it may fail or succeed. Then you can use an optional error: if it is nil , the task succeeded, otherwise it contains an error.

When your main task is completed, call the completion handler with the result.

Note. . You must make sure that the completion handler will eventually be called!

 func updateContacts(completion: (ErrorType?)-> ()) { friendsURL.observeSingleEventOfType(.Value, withBlock: { snapshot in ... ... ... usersURL.observeSingleEventOfType(.Value, withBlock: { snapshot in ... let error = // nil or an error completion(error) return } completion(nil) } } 

Now that you have an array of asynchronous subtasks that will be called in parallel, and you want to pass the completion of updateContacts when all the subtasks are complete, you can use the send groups:

 let group = dispatch_group_create() var error: ErrorType? contactNumbers.forEach { number in dispatch_group_enter(group) queryAsync(number) { (result, error) in if let error = error { // handle error } else { ... } dispatch_group_leave(group) } } dispatch_group_notify(group, queue) { // call the completion handler of your function `updateContacts`: completion(error) } 
+4
source

Source: https://habr.com/ru/post/1241381/


All Articles