Eşzamanlı canlı URL'leri Birleştir ile nasıl sınırlayabilirim?

0

Soru

Görüntüler için çok fazla (~200) url'm var ve her birini indirmem, sonra işlemem (yeniden boyutlandırmam) ve ardından önbelleği güncellemem gerekiyor. Mesele şu ki-sadece bir kerede en fazla 3 istekte bulunmak istiyorum ve görüntüler ağır olduğundan, işlenmeyi bekleyen (ve bellek alan) çok fazla yanıtın "askıda kalmasını" istemiyorum...).

TLDR Bir sonraki (4.) ağ isteğini yalnızca receiveValue in the sink ilk 3 istekten birinde çağrılır... (yani, ağ yanıtı ve işlemden sonra her ikisi de yapılır...).

Bu akış işe yarayacak mı ve bekleyen url'leri tutacak ve onları yere düşürmeyecek mi?

Ayrıca buna ihtiyacım var mı buffer() Ara? Bu cevabı gördükten sonra kullanıyorum: https://stackoverflow.com/a/67011837/2242359

wayTooManyURLsToHandleAtOnce // this is a `[URL]`
    .publisher
    .buffer(size: .max, prefetch: .byRequest, whenFull: .dropNewest) // NEEDED?
    .flatMap(maxPublishers: .max(3)) { url in
       URLSession.shared
           .dataTaskPublisher(for: url)
           .map { (data: Data, _) -> Picture in
               Picture(from: data)
           }
    }
    .tryCompactMap {
        resizeImage(picture: $0) // takes a while and might fail
    }
    .receive(on: DispatchQueue.main)
    .sink { completion
        // handling completion... 
    } receiveValue: { resizedImage
        self.cache.append(resizedImage)
    }
    .store(...)
combine swift urlsession
2021-11-23 22:14:45
1

En iyi cevabı

0

Bir konu kullanırdım. Bu en uygun çözüm değil ama işe yarıyor gibi görünüyor ve belki başka fikirleri tetikleyecektir

var cancellable: AnyCancellable?

var urls: [String] = (0...6).map { _ in "http://httpbin.org/delay/" + String((0...2).randomElement()!) }

var subject: PassthroughSubject<[String], Never> = .init()

let maxConcurrentRequests = 3

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    
    print(urls)
    
    cancellable = subject
        .flatMap({ urls -> AnyPublisher<[URLSession.DataTaskPublisher.Output], URLError> in
            let requests = urls.map { URLSession.shared.dataTaskPublisher(for: URL.init(string: $0)!) }
            return Publishers.MergeMany(requests)
                .collect().eraseToAnyPublisher()
        })
        .print()
        .sink(receiveCompletion: { completion in
            print(completion)
        }, receiveValue: { value in
            print(value)
            if self.urls.count <= self.maxConcurrentRequests {
                self.urls.removeAll()
                self.subject.send(completion: .finished)
            } else {
                self.urls.removeLast(self.maxConcurrentRequests)
                self.subject.send(self.urls.suffix(self.maxConcurrentRequests))
            }
        })
    
    subject.send(urls.suffix(maxConcurrentRequests))
}
2021-11-24 11:30:11

Aramazdım self.subject.send(completion: .finished) aboneliğim sonsuza dek sona erecek mi? (yani, gelecekteki değerleri görmezden gelmek)
Aviel Gross

@AvielGross Evet, öyle. Görünüm denetleyicisi başına bir kez oluşturulan URL koleksiyonunuzun mevcut / görevden alındığını anladım. Eğer doğru değilse, o zaman göndermeyin ".bitti " ancak url'ler dizisinde didSet gibi bir tetikleyiciniz veya konuyla yeniden başlatmak için başka bir tetikleyiciniz var.diziyi boşalttıktan ve yeniden doldurduktan sonra gönderin.
Blazej SLEBODA

Diğer dillerde

Bu sayfa diğer dillerde

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................