使用 URLSession 和 Combine 的间歇性结果

intermittent results using URLSession with Combine

我在 playground 中有以下代码 运行,它应该根据随机类别 ID 打印 4 条线索的数组。用于获取线索的类别ID和正确的URL总是打印正确但是,线索结果有时是间歇性打印的,有时是成功的。谁能帮我弄清楚为什么它有时不打印线索数组但 URL 是正确的?

import Foundation
import Combine

// MARK: - ClueElement
struct ClueElement: Codable {
  let id: Int
  let answer, question: String
  let value: Int
  let categoryID: Int
  let category: Category

  enum CodingKeys: String, CodingKey {
    case id, answer, question, value
    case categoryID = “category_id”
    case category
  }
}


// MARK: - Category
struct Category: Codable {
  let id: Int
  let title: String
  let cluesCount: Int

  enum CodingKeys: String, CodingKey {
    case id, title
    case cluesCount = “clues_count”
  }
}


enum HTTPError: LocalizedError {
  case statusCode
  case post
}



typealias Clue = [ClueElement]

var cancellable: AnyCancellable?

func loadData() {
  let url1 = URL(string: “http://www.jservice.io/api/random”)!
  cancellable = URLSession.shared.dataTaskPublisher(for: url1)
    .map { [=10=].data }
    .decode(type: Clue.self, decoder: JSONDecoder())
    .tryMap { category in
      guard let categoryID = category.first?.categoryID else { throw HTTPError.post}
      guard let cluesCount = category.first?.category.cluesCount else { throw HTTPError.post}
      print(“\(categoryID)“)
      return (categoryID,cluesCount)
  }
  .flatMap { (categoryID,cluesCount) in
    return getClues(for: categoryID, cluesCount: cluesCount)
  }
  .receive(on: DispatchQueue.main)
  .sink(receiveCompletion: { completion in

  }) { clues in
    print(clues)
  }
}

func getClues(for id: Int, cluesCount: Int) -> AnyPublisher<Clue, Error> {
  let url = URL(string: “http://www.jservice.io/api/clues?category=\(id)&offset=\(cluesCount - 4)“)!
  print(url)
  return URLSession.shared.dataTaskPublisher(for: url)
    .map { [=10=].data }
    .decode(type: Clue.self, decoder: JSONDecoder())
    .receive(on: DispatchQueue.main)
    .eraseToAnyPublisher()
}

loadData()

在您的 receiveCompletion: 闭包中放置一个打印语句,您将了解为什么您的代码有时不打印。

.sink(
    receiveCompletion: { completion in
        print(completion)
    },
    receiveValue: { clues in
        print(clues)
    }
)

我做的时候看到了这个:

failure(Swift.DecodingError.valueNotFound(Swift.Int, Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 2", intValue: 2), CodingKeys(stringValue: "value", intValue: nil)], debugDescription: "Expected Int value but found null instead.", underlyingError: nil)))