How to perform an action only after data are downl

2020-02-07 10:10发布

I'm trying to figure out how to trigger an action only after the observeSingleEvent in Firebase has finished its work.

The reason behind is that I need to do the following operations:

  • According to one input from the user I need to get some data from the database
  • When these data are completely downloaded, I need to process them a little bit and use to retrieve other data to be shown to the user

Currently I'm using this code:

    let listOfTags = [String]()
    var outputArray = [String]()

    if listOfTags.count != 0 {
        for tag in listOfTags {

            ref.child("tags").child(tag).observeSingleEvent(of: .value, with: { (snapshot) in

                if let temp = snapshot.children.allObjects as? [FIRDataSnapshot] {
                    for elem in temp {
                        outputArray.append(elem.key)
                    }
                }

                // ...
            }) { (error) in
                print(error.localizedDescription)
            }
        }

        // HERE I WANT TO DO AN ACTION "ONLY" AFTER THE FOR LOOP IS
        // COMPLETED AND THE "outputArray" IS FILLED WITH ALL VALUES
        doSomethingHere()

    }

But I noticed that the function doSomethingHere() is executed immediately when the outputArray is still EMPTY! So it does nothing.

Then my question is, how can I structure the program such that this function is executed after the downloading process is completed? Maybe observeSingleEvent is not the correct Firebase method to be used? For this specific case I don't want to observe any change (because this list is not changing so often), I just need to download data and do something else with these data later ..

1条回答
贪生不怕死
2楼-- · 2020-02-07 10:29

Firebase is asynchronous so to make code execute in a defined order, you need to 'wait' for firebase to return data.

The closures that go with Firebase functions do just that - the code within the closure executes when the data (snapshot) is valid.

Move doSomethingHere() to within the Firebase closure and it will execute in the correct order - in this case

if listOfTags.count != 0 {
    for tag in listOfTags {

        ref.child("tags").child(tag).observeSingleEvent(of: .value, with: { (snapshot) in

            if let temp = snapshot.children.allObjects as? [FIRDataSnapshot] {
                for elem in temp {
                    outputArray.append(elem.key)
                }
                doSomethingHere() //array is populated at this point
            }
        })
    }
}

Note you can also remove this

if listOfTags.count != 0

as if listOfTags is 0, the for loop will not execute.

查看更多
登录 后发表回答