后续有序的HTTP调用

ctehm74n  于 2022-10-04  发布在  Swift
关注(0)|答案(1)|浏览(132)

我正在为HackerNews构建一个简单的iOS客户端。我正在使用their APIs,根据它,我将能够获得已排序的帖子ID(按new、Best和top排序)和将ID传递给请求的单个帖子项目。我面临的问题如下:一旦我获得了ID数组,我如何才能以有序的方式对每个帖子进行HTTP调用?以我目前的实现方式,我没有任何运气。例如,假设ID数组为[3001,3002,3003,3004]。我尝试调用该方法以在for循环中获取那些发布分派组和分派信号量的帖子,但我仍然将它们视为无序的,比如对项目3003的调用在3002之前完成,依此类推。

我使用的方法是:

@Published var posts: [Post] = []

    func getPosts(feedType: FeedType){
        posts = []

        self.getFeedIDs(feedType: feedType).subscribe{ ids in
            let firstFifteen = ids[0...15]

            let dGroup = DispatchGroup()
            let dQueue = DispatchQueue(label: "network-queue")
            let dSemaphore = DispatchSemaphore(value: 0)

            dQueue.async {
                for id in firstFifteen{
                    dGroup.enter()
                    self.getPost(id: id).subscribe{ post in
                        self.posts.append(post)
                        dSemaphore.signal()
                        dGroup.leave()
                    }
                    dSemaphore.wait()
                }
            }
        }
    }

    func getFeedIDs(feedType: FeedType) -> Observable<[Int]> {
        return self.execute(url: URL(string: "https://hacker-news.firebaseio.com/v0/(feedType)stories.json")!)
    }

    func getPost(id: Int) -> Observable<Post>{
        return self.execute(url: URL(string: "https://hacker-news.firebaseio.com/v0/item/(id).json")!)
    }

func execute <T: Decodable>(url: URL) -> Observable<T> {
        return Observable.create { observer -> Disposable in
            let task = URLSession.shared.dataTask(with: url) { res, _, _ in
                guard let data = res, let decoded = try? JSONDecoder().decode(T.self, from: data) else {
                    return
                }

                observer.onNext(decoded)
                observer.onCompleted()
            }
            task.resume()

            return Disposables.create {
                task.cancel()
            }
        }
    }

任何帮助都将不胜感激。

ujv3wf0j

ujv3wf0j1#

信号量没有任何意义,而且效率也很低。

使用Apple建议与TaskGroups结合使用的相同模式:收集词典中的数据,并在收到通知后按词典键对数据进行排序

func getPosts(feedType: FeedType){
    var postData = [Int:Post]()
    posts = []

     self.getFeedIDs(feedType: feedType).subscribe{ ids in
         let firstFifteen = ids[0...15]

         let dGroup = DispatchGroup()

         for (index, element) in firstFifteen.enumerated() {
             dGroup.enter()
             self.getPost(id: element).subscribe{ post in
                 postData[index] = post
                 dGroup.leave()
             }   
         }

         dGroup.notify(queue: .main) {
             for key in postData.keys.sorted() {
                 posts.append(postData[key]!)
             }
         }
     }
 }

相关问题