35

defer有人可以解释一下和create方法之间的区别Observable吗?我不明白什么时候应该使用defer,什么时候应该使用create..

参考:

推迟:http ://reactivex.io/documentation/operators/defer.html

创建:http ://reactivex.io/documentation/operators/create.html

谢谢

4

3 回答 3

29

因此,区别似乎是:defer当您已经拥有创建/返回可观察对象的东西时很好,但是您不希望该过程在订阅之前发生。

create当您需要手动包装异步进程并创建 observable 时,这是很好的选择。该创建推迟到订阅。

换一种方式:

defer是一个能够延迟组合可观察序列的运算符。

create是可观察序列的自定义实现(创建被推迟到订阅)。

因此,如果您有可能使用从某些结果/值just创建一个的情况,Observable或者您有一个返回Observable请求的网络 API 层,但您不希望该请求在订阅之前启动。defer对于那些场景会很好。

如果你有一个网络 API 层返回Observable请求,但你需要一个Observable接口,你可以使用create. 该Observable序列仍然不会在订阅之前创建。如果您希望无论订阅如何都启动该网络调用,那么您将使用不同的机制,例如 a Subject,可能会重播。

于 2017-01-24T16:10:11.733 回答
22

create(...) 实际上会立即创建 Observable。

    public final static <T> Observable<T> create(OnSubscribe<T> f) {
        return new Observable<T>(hook.onCreate(f));
    }

defer(...) 接受返回 Observable(Subject, etc...) 的 Factory 函数,用 OnSubscribeDefer 包装它并仅在订阅者订阅时创建 Observable,为每个订阅者创建新的 Observable。

public final static <T> Observable<T> defer(Func0<Observable<T>> observableFactory) {
    return create(new OnSubscribeDefer<T>(observableFactory));
}

在此处查看更多详细信息

于 2016-03-30T18:17:21.863 回答
0

以示例的方式,对上面已经给出的非常好的答案进行了另一种看法。

假设您有一个基于其内部状态返回 Observable 的类(用类似 Javascript 的伪语言编写,但适用于所有 ReactiveX 实现)

class DownloadManager {

  var uuid = nil  // this only gets set during runtime...say when a user performs a certain action

  // fetches some data from the server.
  func get() -> Observable<Data> {
    if uuid == nil {
      return .error(new DownloadUuidEmptyError())
    }
 
    return network.download(uuid, ...) // do something with the non nil uuid
  }
}

以这种方式编写,可能会调用该方法,并且在实际评估它之前传递 observable,并且 uuid 可能在方法调用时不存在,但在订阅 Observable 时存在,从而产生错误。

let observable = manager.get()

// ... at some point, uuid is assigned to
// then we subscribe to our observable ...

observable.subscribe(...).disposedBy(bag) // errors!

在这种情况下,defer 可以派上用场,以确保在订阅时间之前不会进行评估(例如 uuid)。

  // fetches some data from the server.
  func get() -> Observable<Data> {
    return Observable.defer {
      if uuid == nil {
        return .error(new DownloadUuidEmptyError())
      }

      return network.download(uuid, ...) // do something with the non nil uuid
    }
  }

现在,上面的示例将不再出错。也许更大的目标是确保您的代码永远不会达到这种状态,但有时它并不实用。这种模式对我来说很方便。

于 2020-07-06T14:41:06.180 回答