Swift Combine:如何从发布者列表中创建单个发布者?

编程入门 行业动态 更新时间:2024-10-24 15:12:40
本文介绍了Swift Combine:如何从发布者列表中创建单个发布者?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

使用Apple的新的Combine框架,我希望从列表中的每个元素发出多个请求.然后,我希望减少所有响应得到一个结果.基本上,我想从发布者列表转到拥有响应列表的单个发布者.

Using Apple's new Combine framework I want to make multiple requests from each element in a list. Then I want a single result from a reduction of all the the responses. Basically I want to go from list of publishers to a single publisher that holds a list of responses.

我曾尝试制作一个发布者列表,但我不知道如何将列表缩小为一个发布者.而且我尝试过使发布者包含一个列表,但是我无法平面映射发布者列表.

I've tried making a list of publishers, but I don't know how to reduce that list into a single publisher. And I've tried making a publisher containing a list but I can't flat map a list of publishers.

请查看"createIngredients"功能

Please look at the "createIngredients" function

func createIngredient(ingredient: Ingredient) -> AnyPublisher<CreateIngredientMutation.Data, Error> { return apollo.performPub(mutation: CreateIngredientMutation(name: ingredient.name, optionalProduct: ingredient.productId, quantity: ingredient.quantity, unit: ingredient.unit)) .eraseToAnyPublisher() } func createIngredients(ingredients: [Ingredient]) -> AnyPublisher<[CreateIngredientMutation.Data], Error> { // first attempt let results = ingredients .map(createIngredient) // results = [AnyPublisher<CreateIngredientMutation.Data, Error>] // second attempt return Publishers.Just(ingredients) .eraseToAnyPublisher() .flatMap { (list: [Ingredient]) -> Publisher<[CreateIngredientMutation.Data], Error> in return list.map(createIngredient) // [AnyPublisher<CreateIngredientMutation.Data, Error>] } }

我不确定如何获取发布者数组并将其转换为包含数组的发布者.

I'm not sure how to take an array of publishers and convert that to a publisher containing an array.

类型"[AnyPublisher]"的结果值与关闭结果类型"Publisher"不符

Result value of type '[AnyPublisher]' does not conform to closure result type 'Publisher'

推荐答案

本质上,在您的特定情况下,您正在寻找的是这样的东西:

Essentially, in your specific situation you're looking at something like this:

func createIngredients(ingredients: [Ingredient]) -> AnyPublisher<[CreateIngredientMutation.Data], Error> { Publishers.MergeMany(ingredients.map(createIngredient(ingredient:))) .collect() .eraseToAnyPublisher() }

这将收集"上游发布者产生的所有元素,并在它们全部完成之后生成包含所有结果的数组,并最终完成自身.

This 'collects' all the elements produced by the upstream publishers and – once they have all completed – produces an array with all the results and finally completes itself.

请记住,如果上游发布者之一失败-或产生多个结果-元素数量可能与订阅者数量不匹配,因此您可能需要其他运营商来缓解这种情况.

Bear in mind, if one of the upstream publishers fails – or produces more than one result – the number of elements may not match the number of subscribers, so you may need additional operators to mitigate this depending on your situation.

更通用的答案,您可以使用 EntwineTest框架对其进行测试:

The more generic answer, with a way you can test it using the EntwineTest framework:

import XCTest import Combine import EntwineTest final class MyTests: XCTestCase { func testCreateArrayFromArrayOfPublishers() { typealias SimplePublisher = Just<Int> // we'll create our 'list of publishers' here. Each publisher emits a single // Int and then completes successfully – using the `Just` publisher. let publishers: [SimplePublisher] = [ SimplePublisher(1), SimplePublisher(2), SimplePublisher(3), ] // we'll turn our array of publishers into a single merged publisher let publisherOfPublishers = Publishers.MergeMany(publishers) // Then we `collect` all the individual publisher elements results into // a single array let finalPublisher = publisherOfPublishers.collect() // Let's test what we expect to happen, will happen. // We'll create a scheduler to run our test on let testScheduler = TestScheduler() // Then we'll start a test. Our test will subscribe to our publisher // at a virtual time of 200, and cancel the subscription at 900 let testableSubscriber = testScheduler.start { finalPublisher } // we're expecting that, immediately upon subscription, our results will // arrive. This is because we're using `just` type publishers which // dispatch their contents as soon as they're subscribed to XCTAssertEqual(testableSubscriber.recordedOutput, [ (200, .subscription), // we're expecting to subscribe at 200 (200, .input([1, 2, 3])), // then receive an array of results immediately (200, pletion(.finished)), // the `collect` operator finishes immediately after completion ]) } }

更多推荐

Swift Combine:如何从发布者列表中创建单个发布者?

本文发布于:2023-11-13 14:23:12,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1584561.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:发布者   列表中   Swift   Combine

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!