ยังไงเพื่อจำกัด concurrent อยู่ URLSessions กับรวบรว?

0

คำถาม

ผมมีเรื่องมากมายให้ต้อง(~200)ที่อยู่ url สำหรับภาพต่างๆแล้วฉันต้องการที่จะดาวน์โหลดแต่ละคนงั้นโพรเซส(ปรับขนาดมันแล้วปรับปรุงแคช เรื่องก็คือ-ฉันแค่อยากจะต้องตอนแม็กซ์ 3 ร้องของที่ครั้งหนึ่งแล้วตั้งภาพเป็นหนักฉันก็ไม่อยากเป็นมากมายจะฟื้นคืนชีพ"อยู่"รอคอยที่จะถูกประมวลผล(และจะเอาความทรงจำ...).

TLDR ฉันอยากโทรหาคนต่อไป(4)บนเครือข่ายการร้องขอเพียงหลัง receiveValue ใน sink เป็นชื่อบนหนึ่งในแรงบันดาลของฉันเมื่อ 3 คำขอร้อง...(ie หลังจากเครือข่ายการตอบสนอ&กำลังประมวลผลเป็นทั้งสองทำ...).

เรื่องนี้มันไหลเวียนงานและมันจะเก็บมันไว้รอที่อยู่ url และไม่ทิ้งพวกเขานอนอยู่บนพื้น?

ยังฉันต้องการมัน buffer() โทรหา? ฉันใช้มันหลังจากเห็นนี่คำตอบ: 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

คำตอบที่ดีที่สุด

0

ฉันคงต้องใช้เรื่องนี้มาตลอด นี่ไม่ใช่คำที่เหมาะสมทางออกแต่มันดูเหมือนทำงานและอาจจะกระตุ้นความคิดอื่น

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

ไม่โทรมา self.subject.send(completion: .finished) ไว้บนอ่างจบการสมัครสมาชิกของฉันตลอดไปเหรอ? (ie ไม่สนใจเรื่องอนาคตค่าของ emitted)
Aviel Gross

@AvielGross มันหมายความว่าอย่างนั้น. ฉันเข้าใจว่าของสะสมของที่อยู่ url ที่ถูกสร้างครั้งต่อมุมมอง controller ของขวัญ/ไม่สนใจ. ถ้ามันไม่ใช่เรื่องจริงงั้นก็ทำไม่ได้ส่ง".เสร็จแล้วแต่คุณมีกระตุ้นเหมือน didSet บที่อยู่ url อาเรย์อีกหรือเพื่อ relaunch กับเรื่องนี้มาตลอดส่งหลังกำลังหยิบอาเรย์และ refilling มัน
Blazej SLEBODA

ในภาษาอื่นๆ

หน้านี้อยู่ในภาษาอื่นๆ

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