Finish all asynchronous requests before loading data?

前端 未结 6 914
被撕碎了的回忆
被撕碎了的回忆 2020-11-27 18:57

I have run into an issue where I have multiple asynchronous requests occuring which grab images and information from the Facebook API and my Firebase database. I want to per

6条回答
  •  鱼传尺愫
    2020-11-27 19:44

    While there is definitely solution with using GCD and stuff around it, synchronization in general is pain and the more your code gets complicated, the more problems it will start showing - but I think there is one-for-all solution to that: Bolts framework from Facebook (both for android na iOS)

    Bolts Framework usage

    So what is so magical about it? Well, it lets you create "Tasks", and then chain them. The method in particular that you are interested in is taskForCompletionOfAllTasks: , which is made for parallel processing, just what you need. I wrote a little example for you which you can adjust to your needs:

    func fetchAllInformation() -> BFTask {
    
        // First, create all tasks (if you need more, than just create more, it is as easy as that
        var task1 = BFTaskCompletionSource()
        var task2 = BFTaskCompletionSource()
        var tasks = [task1, task2]
    
        // What you do, is you set result / error to tasks and the propagate in the chain upwards (it is either result, or error)
        // You run task 1 in background
        API.instance.fetchFirstDetailsInBackgroundWithBlock {
            (object: AnyObject!, error: NSError!) -> Void in
    
            // On error or on success, you assign result to task (whatever you want)
            if error == nil {
                task1.setResult(object)
            } else {
                task1.setError(error)
            }
        }
    
        // You run task 2 in background
        API.instance.fetchSecondDetailsInBackgroundWithBlock {
            (object: AnyObject!, error: NSError!) -> Void in
    
            // On error or on success, you assign result to task (whatever you want)
            if error == nil {
                task2.setResult(object)
            } else {
                task2.setError(error)
            }
        }
    
        // Now you return new task, which will continue ONLY if all the tasks ended
        return BFTask(forCompletionOfAllTasks: tasks)
    }
    

    Once you have main method done, you can use bolts chaining magic:

    func processFullObject() {
    
        // Once you have main method done, you can use bolts chaining magic
        self.fetchAllInformation().continueWithBlock { (task : BFTask!) -> AnyObject! in
    
            // All the information fetched, do something with result and probably with information along the way
            self.updateObject()
        }
    }
    

    The Bolts framework documentation / README covers basically everything there is to know about it and it is quite extensive, so I would suggest you to go through it - it is very easy to use once you get the basics. I personally use it for exactly this, and it is a blast. This answer will hopefully provide you with different solution and approach, possibly a cleaner one.

提交回复
热议问题