#swift #combine
Вопрос:
Общий вариант использования-4 сетевых запроса
- A. Запросы 1 и 2 должны выполняться параллельно и ждать завершения обоих
- B. Запрос 3 выполняется после завершения 1 и 2
- C. Запрос 4 выполняется после завершения 3
После C конечный результат должен иметь AnyPublisher
тип
Я пытаюсь использовать Combine для достижения вышеуказанного, и до сих пор я могу использовать Publishers.Zip
A и C с помощью flatMap
. С чем я борюсь, так это с Б. Я могу сделать это, используя вложенные обработчики завершения, но не используя flatMap
Это пример кода со строками (не фактический код)
func overallFunc(arg1: "arg1", arg2: "arg2", arg3: "arg3", arg4: "arg4" ) -gt; AnyPublisherlt;String?, Errorgt; { let pub1 = func1(arg1: arg1, arg2: arg2) let pub2 = func2(arg1: arg3, arg2: arg4) let combinedPub = Publishers.Zip(pub1, pub2) combinedPub .flatMap {(response1, response2) in return func3(arg1: response1.attribute1, arg2: response2.attribute2) } }
func1
, func2
и func3
все возвраты URLSession.shared.dataTaskPublisher
с типом возврата говорят AnyPublisherlt;String?, Errorgt;
Сейчас я борюсь с завершением кода для overallFunc
. Разработчик выдает следующую ошибку flatMap
.
Type of expression is ambiguous without more context
Если я добавлю дополнительное значение в последнюю строку overallFunc
, то ошибка изменится на No 'flatMap' candidates produce the expected contextual result type 'AnyPublisherlt;String?, Errorgt;'
Короче говоря, я хочу использовать flatMap
результат Publishers.Zip
и вернуть другого издателя, чтобы я мог добавить другого flatMap
для выполнения 4-го запроса, но не могу понять правильный синтаксис и порядок действий для этого.
Комментарии:
1. Попробуйте явно добавить типы для аргументов
flatMap
закрытия и возвращаемого типа, компилятор должен выдать вам лучшее сообщение об ошибке.2. Я совершенно уверен, что у вас есть несоответствие типа возврата. Однако это помогло бы увидеть сигнатуры методов для всех ваших методов (т. Е.: func1/2/3). Вы должны опубликовать полный пример. Я также не понимаю, что вы планируете вернуть из overallFunc. combinedPub? combinedPub.eraseToAnyPublisher()? и т. Д.
3. @Cristik Спасибо! Добавление типа возвращаемого значения помогло и дало более полезные сообщения об ошибках.
4. @Cristik Если вы предоставите свой комментарий в качестве ответа, я могу принять его как решение.
5. Я только предложил метод отладки, и я чувствую, что это не подходит для ответа. Вместо этого вам следует добавить ответ с внесенными вами изменениями в коде и, возможно, упомянуть в ответе, что комментарий помог вам.
Ответ №1:
Я думаю, что ваша попытка запутать код устранила проблему, с которой вы столкнулись. Следующий код компилируется просто отлично:
func func1(arg1: String, arg2: String) -gt; AnyPublisherlt;String?, Errorgt; { fatalError() } func func2(arg1: String, arg2: String) -gt; AnyPublisherlt;String?, Errorgt; { fatalError() } func func3(arg1: String, arg2: String) -gt; AnyPublisherlt;String?, Errorgt; { fatalError() } func func4(arg1: String) -gt; AnyPublisherlt;String?, Errorgt; { fatalError() } func overallFunc(arg1: String, arg2: String, arg3: String, arg4: String) -gt; AnyPublisherlt;String?, Errorgt; { Publishers.Zip( func1(arg1: arg1, arg2: arg2), func2(arg1: arg3, arg2: arg4) ) .flatMap { (response1, response2) in func3(arg1: response1 ?? "", arg2: response2 ?? "") } .flatMap { response3 in func4(arg1: response3 ?? "") } .eraseToAnyPublisher() }
Комментарии:
1. Извините, в следующий раз приведу более конкретный пример. Спасибо вам за ответ! Добавление
.eraseToAnyPublisher
помогло немного лучше изолировать проблему. Что решило эту проблему, так это явное добавление возвращаемого типа вflatMap
закрытие.2. Ах да. Если у вас есть более одной строки кода на плоской карте, то вам обычно приходится определять тип возвращаемого значения (если только за пределами закрытия нет чего-то, что проясняет компилятору, каким должен быть тип возвращаемого значения).
Ответ №2:
Результатом flatMap
будет a String?
(результат запроса 3), к которому вы затем захотите перейти map
. Это map
преобразует строку в четвертый запрос. Затем вы можете добавить подписчика к четвертому запросу, который будет результатом вашей общей последовательности. Так…
pub1 .zip(pub2) .flatMap { (response1, response2) in func3(arg1: response1.attribute1, arg2: response2.attribute2) } .map { (func3Result : String?) in /* return publisher of 4th request */ } .eraseToAnyPublisher()
Результатом всего этого станет публикация 4-го запроса.