Alex Chen
Alex Chen

Reputation: 21

Weird behaviour when querying data from firebase database

I am trying to write some data in firebase database, however i got the wrong running process. Could somebody help me with it? Many thanks!!

The JSON tree structure is like as follows:

{ 
    "cars": {

        "auto id": [

            "parts": "wheel"
             ...
    .
    .
    .



@objc func buttonTapped(){

    print("before running")
        var ref = Database.database().reference(withPath: "cars").queryOrdered(byChild: "parts").queryEqual(toValue: "wheel")
            ref.observeSingleEvent(of: .childAdded, with: { (snapshot) in
            autoId = snapshot.key
            print("running")
        }) { (error) in
            print(error.localizedDescription)
        }
print("after running")
let newPlanetRef = Database.database().reference().child("company").childByAutoId()
                    newPlanetRef.updateChildValues(autoId)
}

I expect the running process is

"before running"->"running"->"after running"

But the actual process is

"before running"->"after running"->"running" And the data cannot be updated to database unless I put the update function inside the closure

Upvotes: 0

Views: 78

Answers (1)

emrcftci
emrcftci

Reputation: 3516

This is an async process.

You should use like this:

var newPlanetRef: String? //It should be your reference type

var ref = Database.database().reference(withPath: "cars").queryOrdered(byChild: "parts").queryEqual(toValue: "wheel")
        ref.observeSingleEvent(of: .childAdded, with: { (snapshot) in
        autoId = snapshot.key
        newPlanetRef = Database.database().reference().child("company").childByAutoId()
        newPlanetRef.updateChildValues(autoId)
        print("running")
    }) { (error) in
        print(error.localizedDescription)
    }

But I think use like this:

  • Create private enum for your reference keys:

    private enum ReferenceKeys {
        static let carsKey = "cars"
    }
    
  • Create global variables of your database references:

    var database = Database.database()
    var databaseReference = database.reference()
    var carReference = database.reference(withPath: ReferencesKeys.carsKey)
    
  • Use your function like this:

    var newPlanetRef: String?
    
    var reference = carReference.queryOrdered(byChild: "parts").queryEqual(toValue: "wheel")
    
    reference.observeSingleEvent(of: .childAdded, with: { [weak self] snapshot in
    
        self?.autoId = snapshot.key
        newPlanetRef = databaseReference.child("company").childByAutoId()
        newPlanetRef.updateChildValues(autoId)
    
        print("running")
    }) { error in 
    
        print(error.localizedDescription)
    }
    

Bonus:

You can use dispatchGroup (or semaphore) to wait snapshot value for proceed:

DispatchGroup

@objc func buttonTapped(){

    let dispatchGroup = DispatchGroup()

    print("before running")
    var ref = Database.database().reference(withPath: "cars").queryOrdered(byChild: "parts").queryEqual(toValue: "wheel")

    dispatchGroup.enter()
    ref.observeSingleEvent(of: .childAdded, with: { [weak self]snapshot in
            self?.autoId = snapshot.key

            dispatchGroup.leave()
            print("running")
    }) { (error) in
            print(error.localizedDescription)
    }
    print("after running")
    let newPlanetRef = Database.database().reference().child("company").childByAutoId()
    newPlanetRef.updateChildValues(autoId)
}

DispatchSemaphore

@objc func buttonTapped(){

    let dispatchSemaphore = DispatchSemaphore(value: 1)

    print("before running")
    var ref = Database.database().reference(withPath: "cars").queryOrdered(byChild: "parts").queryEqual(toValue: "wheel")

    ref.observeSingleEvent(of: .childAdded, with: { [weak self]snapshot in
            self?.autoId = snapshot.key
            semaphore.signal()

            print("running")
    }) { (error) in
            print(error.localizedDescription)
    }

    semaphore.wait()

    print("after running")
    let newPlanetRef = Database.database().reference().child("company").childByAutoId()
    newPlanetRef.updateChildValues(autoId)
}

Completion

@objc func buttonTapped(){

    getData { [weak self] snapshotKey in
        self?.autoId = snapshot.key
        let newPlanetRef = Database.database().reference().child("company").childByAutoId()
        newPlanetRef.updateChildValues(self?.autoId)
    }
}

/// completion type -(String?)- must be a snapshot.key's type
func getData(_ completion: @escaping (String?) -> Void) {

    print("before running")
    var ref = Database.database().reference(withPath: "cars").queryOrdered(byChild: "parts").queryEqual(toValue: "wheel")

    ref.observeSingleEvent(of: .childAdded, with: { snapshot in
            completion?(snapshot.key)

            print("running")
    }) { (error) in
            print(error.localizedDescription)
    }

    print("after running")

}

Upvotes: 1

Related Questions