Невозможно определить тип возврата сложного замыкания; добавить явный тип для устранения неоднозначности в RxSwift - PullRequest
0 голосов
/ 05 сентября 2018

Мне нужно сделать несколько звонков.

1. Удалить загрузку документа

2. Изображение 1 и сервер возвращает URL

3. Загрузить изображение 2 и сервер вернет URL

4. API для создания документов содержит как URL, так и дополнительные
параметры.

Код, который я пытался написать, находится в RxSwift & MVVM.

  let resultOfDocumentUpdateWithDelete =
            donepressed
                .filter{ $0 }
                .withLatestFrom(self.existingDocumentIDChangedProperty)
                .flatMapLatest {id in
                    let deleted_document = apiClient.deleteDocument(id).asObservable().materialize()
                    let upload_frontImage = deleted_document
                        .withLatestFrom(self.frontImageNameChangedProperty)
                        .flatMapLatest {image in
                            apiClient.uploadImage(image: image!).asObservable().materialize()
                    }
                    let upload_backImage = upload_frontImage
                        .withLatestFrom(self.backImageChangedProperty)
                        .flatMapLatest {image in
                            apiClient.uploadImage(image: image!).asObservable().materialize()
                    }

                    let upload_document = upload_backImage
                        .withLatestFrom(self.parametersChangedProperty)
                        .flatMapLatest {parameters in
                            apiClient.uploadDocument(parameters: parameters)
                    }

                    return upload_document.materialize()
                }
                .share(replay: 1)

Убедитесь, что два ответа сервера введены в последнем API, поэтому все они будут вызваны в последовательности.

как это сделать в RxSwift.

1 Ответ

0 голосов
/ 05 сентября 2018

Это было интересно! Вывод здесь заключается в том, что когда вы сомневаетесь, сделайте свой собственный оператор. Если выясняется, что вы позже выясните, как выполнять работу, используя встроенные операторы, то вы можете заменить свои. Единственное, что нужно сделать самостоятельно, это то, что они требуют гораздо большего тестирования.

Обратите внимание: чтобы использовать нижеприведенное, вам нужно будет объединить последние из ваших наблюдаемых, а затем flatMap и передать их значения в эту функцию.

// all possible results from this job.
enum ProcessResult {
    case success
    case deleteFailure(Error)
    case imageFailue(Error)
    case backImageFailure(Error)
    case documentFailure(Error)
}

func uploadContent(apiClient: APIClient, documentID: Int, frontImage: UIImage, backImage: UIImage, parameters: Parameters) -> Single<ProcessResult> {
    // instead of trying to deal with all the materializes, I decided to turn it into a single process.
    return Single.create { observer in

        // each api call happens in turn. Note that there are no roll-back semantics included! You are dealing with a very poorly written server.
        let deleted = apiClient.deleteDocument(id: documentID)
            .asObservable()
            .share()

        let imagesUploaded = deleted
            .flatMap { _ in Observable.zip(apiClient.uploadImage(image: frontImage).asObservable(), apiClient.uploadImage(image: backImage).asObservable()) }
            .share()

        let documentUploaded = imagesUploaded
            .flatMap { arg -> Single<Void> in
                let (frontURL, backURL) = arg
                var updatedParams = parameters
                // add frontURL and backURL to parameters
                return apiClient.uploadDocument(parameters: updatedParams)
            }
            .share()

        let disposable = deleted
            .subscribe(onError: { observer(.success(ProcessResult.deleteFailure($0))) })
        let disposable1 = imagesUploaded
            .subscribe(onError: { observer(.success(ProcessResult.imageFailue($0))) })
        let disposable2 = documentUploaded
            .subscribe(
                onNext: { observer(.success(ProcessResult.success)) },
                onError: { observer(.success(ProcessResult.documentFailure($0))) }
        )

        return Disposables.create([disposable, disposable1, disposable2])
    }
}
...