0

I am calling a function to get a result which is an AnyPublisher<[Object], Error>. Now I need to loop through each object and call at least 3 another api calls with the id in a single object.

AnyPublisher<[Object], Error>

|

Loop though the object array

|

with a property in the object, make 3 api calls(async or sync)

|

with the object and the objects i get from each api call, create another object and publish it

How can I do this?

Edit: This is some code that I added to check whether this will work. This is based on the code I found on one of your other posts Combine framework: how to process each element of array asynchronously before proceeding But instead of collecting all the publishers and then coming to map, its going to map after completing the inner flatMap.

What am I doing wrong?

struct FoodDetailInput {
    let appear: AnyPublisher<Void, Never>
}

let appearRecord = PassthroughSubject<Void, Never>()// this is called when the detail page is taken
    let input = FoodDetailInput(appear: appearRecord.eraseToAnyPublisher())

let foodDetails = input.appear
.flatMap({[unowned self] _ in self.dataProvider.ingredients(for: food.id) })
.flatMap({ ingredients -> AnyPublisher<Ingredient, Error> in
    Publishers.Sequence(sequence: ingredients).setFailureType(to: Error.self).eraseToAnyPublisher()
})
.flatMap({[unowned self] singleIngredient  in
    self.dataProvider.variants(for: food.id, ingredientName: singleIngredient.id)
        .flatMap { variants -> AnyPublisher<DetailPageObject, Error> in
            var singleDetailObject = DetailPageObject(ingredient: singleIngredient)
            singleDetailObject.variants = variants
            return Just(singleDetailObject).setFailureType(to: Error.self).eraseToAnyPublisher()
        }
        .collect()
        .map { detailPageObjects -> PageDetailsState  in
            PageDetailsState.success(detailPageObjects)
        }
})
.replaceError(with:PageDetailsState.success([]))
.eraseToAnyPublisher()
wolverine
  • 189
  • 5
  • 20

1 Answers1

1

You are describing .flatMap. Three API calls? You can just chain three .flatMap calls — though if you prefer to do them simultaneously you can configure them in an array and use .flatMap on that. If you use the former approach, uou will need to keep passing both the object (or the accumulated objects) and the id down the chain as you go so that everything you need pops out the end.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I get an array of food-items. So using the id of each food, I will need to make multiple api calls to create one object which will have some information from the food-item and remaining will be populated using the api calls, for eg: one will give as result the array of items used in it, another will give nutrition information etc. – wolverine Feb 28 '23 at 14:03
  • 1
    This would be a lot easier if you could give up your dependency on Combine and use `async/await` instead. But I do really like Combine and I've written an online free book about it: https://www.apeth.com/UnderstandingCombine/ – matt Feb 28 '23 at 14:16
  • Can you please check the code I added. I based it on one of your posts but seems like I am doing something wrong @matt – wolverine Mar 01 '23 at 09:35
  • Even though I never thought like that, thinking from your POV, it surely sounds like I made a demand. Really sorry for that @matt. I have learnt a lot from your posts and comments. Maybe due to that familiarity, I asked like that. I will add a new question and will add the full context for that later. Like you said, my question's answer is there in your comment and I will approve that. – wolverine Mar 01 '23 at 17:40
  • Let me know when you've got the new question ready! I really do want to help. – matt Mar 01 '23 at 18:02