Swift Combine альтернатива Rx Observable.create - PullRequest
0 голосов
/ 14 октября 2019

У меня есть некоторый код, созданный с использованием RxSwift, и я пытаюсь преобразовать его для использования инфраструктуры Apple Combine.

Одним из распространенных шаблонов является использование Observable.create дляснимать наблюдаемые (обычно сетевые запросы). Примерно так:

func loadWidgets() -> Observable<[Widget]> {
  return Observable.create { observer in
    // start the request when someone subscribes
    let loadTask = WidgetLoader.request("allWidgets", completion: { widgets in
      // publish result on success
      observer.onNext(widgets)
      observer.onComplete()
    }, error: { error in
      // publish error on failure
      observer.onError()
    })
    // allow cancellation
    return Disposable {
      loadTask.cancel()
    }
  }
}

Я пытаюсь сопоставить это с Combine, и я не смог до конца понять это. Самое близкое, что я смог получить, - это использовать Future для чего-то вроде этого:

func loadWidgets() -> AnyPublisher<[Widget], Error> {
  return Future<[Widget], Error> { resolve in
    // start the request when someone subscribes
    let loadTask = WidgetLoader.request("allWidgets", completion: { widgets in
      // publish result on success
      resolve(.success(widgets))
    }, error: { error in
      // publish error on failure
      resolve(.failure(error))
    })
    // allow cancellation ???
  }
}

Как вы можете видеть, он делает большую часть этого, но нет возможности отменить. Во-вторых, будущее не допускает многократных результатов.

Есть ли способ сделать что-то вроде шаблона Rx Observable.create, который позволяет отменять и, необязательно, многократные результаты?

1 Ответ

1 голос
/ 15 октября 2019

Из того, что я узнал, поддержка инициализации AnyPublisher с замыканием была исключена в Xcode 11 beta 3. Это было бы соответствующим решением для Observable.create Rx в этом случае, но пока я верючто Future является готовым решением, если вам нужно распространять только одно значение. В других случаях я бы пошел за возвращение PassthroughSubject и распространение нескольких значений таким образом, но это не позволит вам начать задачу, когда начнется наблюдение, и я считаю, что это далеко от идеала по сравнению с Observable.create.

С точки зрения отмены, у него нет свойства isDisposed, аналогичного Disposable, поэтому невозможно напрямую проверить его состояние и остановить выполнение ваших собственных задач. Единственный способ, о котором я могу думать прямо сейчас, - это наблюдать за событием cancel, но это, безусловно, не так удобно, как Disposable. Кроме того, я бы предположил, что cancel на самом деле может остановить такие задачи, как сетевые запросы от URLSession на основе документов здесь: https://developer.apple.com/documentation/combine/cancellable

...