Swift PromiseKit. Выполняйте запросы GET несколько раз, один за другим. Пирамида судьбы с PromiseKit - PullRequest
0 голосов
/ 29 мая 2020

Я выполняю несколько запросов GET к URL-адресу, он возвращает мне некоторые JSON данные, которые я декодирую в класс. Из этого класса я извлекаю атрибут - id: Int , этот id является частью URL-адреса, который я создаю для выполнения другого запроса GET.

Другими словами: JSON получено из URL -> JSON Декодировано -> Идентификатор извлечен -> Создан новый URL -> JSON извлечен из нового URL -> JSON Декодирован ... и этот процесс повторяется n раз.

Сейчас у меня такая же пирамида гибели, но с использованием нотации PromiseKit:


        func fetch_analysis_dataTask(url: String) -> Promise<(data: Data, response: URLResponse)> {
            let urlRequest = APIConnect.urlRequest(endPoint: url, method: .GET, data: nil)
            return URLSession.shared.dataTask(.promise, with: urlRequest).validate()
        }

        let expectation = self.expectation(description: "Async call")
        let urlRequest = APIConnect.urlRequest(endPoint: "test?patient_id=3730", method: .GET, data: nil)

        firstly {
            URLSession.shared.dataTask(.promise, with: urlRequest).validate()
        }.map {
            try JSONDecoder().decode([TestWrapper].self, from: $0.data)
        }.done { testWrappers in
            var tests = [Test]()
            for testWrapper in testWrappers {
                if testWrapper.test != nil {
                    tests.append(testWrapper.test!)
                }
            }

            let testID = tests.first!.id!
            let urlRequest = APIConnect.urlRequest(endPoint: "analysis/" + String(testID), method: .GET, data: nil)

            firstly {
                URLSession.shared.dataTask(.promise, with: urlRequest).validate()
            }.map {
                try JSONSerialization.jsonObject(with: $0.data, options: .allowFragments)
            }.done { data in
                XCTAssert(data != nil)
                expectation.fulfill()
            }.catch { error in
                print(error)
                XCTAssert(false)
                expectation.fulfill()
            }
        }

        waitForExpectations(timeout: 20)
    }

Однако я не вижу способа, как это сделать, но я уверен, что он есть, или?

1 Ответ

0 голосов
/ 29 мая 2020

Если вы используете then вместо done, вы можете вернуть обещание, и оно продолжит цепочку. Примерно так:

let expectation = self.expectation(description: "Async call")
let urlRequest = APIConnect.urlRequest(endPoint: "test?patient_id=3730", method: .GET, data: nil)

firstly {
    URLSession.shared.dataTask(.promise, with: urlRequest).validate()
}.map {
    try JSONDecoder().decode([TestWrapper].self, from: $0.data)
}.then { testWrappers in
    var tests = [Test]()
    for testWrapper in testWrappers {
        if testWrapper.test != nil {
            tests.append(testWrapper.test!)
        }
    }

    let testID = tests.first!.id!
    let urlRequest = APIConnect.urlRequest(endPoint: "analysis/" + String(testID), method: .GET, data: nil)
    return URLSession.shared.dataTask(.promise, with: urlRequest).validate()
}.map {
    try JSONSerialization.jsonObject(with: $0.data, options: .allowFragments)
}.done { data in
    XCTAssert(data != nil)
    expectation.fulfill()
}.catch { error in
    print(error)
    XCTAssert(false)
    expectation.fulfill()
}

waitForExpectations(timeout: 20)

PS. У меня компилятор запутался со сложными цепочками. Аннотирование возвращаемых значений может помочь, но то, что я обычно делаю, - это пытаюсь сделать все map, then, ensure, et c. вызовы имеют один оператор, что может означать использование большего количества map s.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...