Какая разница здесь подписываться на нормальный тип и наблюдаемый тип? - PullRequest
0 голосов
/ 03 февраля 2019
  let s = "Hello World"
  let string = BehaviorSubject(value: s)

  //Example 1
  string
    .map { _ in "hhh" }
    .subscribe(onNext: { element in
      print(element)
    }, onCompleted: {
      print("completed")
    }
  )

  //Example 2
  string
    .flatMap { s -> Observable<String> in
      Observable.just("lll")
    }
    .subscribe(onNext: { element in
      print(element)
    }, onCompleted: {
      print("completed")
    }
  )

  //Example 3
  let aaa = string
    .map { _ in "hhh" }

  //Example 4    
  let bbb = string
    .flatMap { s -> Observable<String> in
      Observable.just("lll")
  }

Я довольно новичок в мире RX, в примерах 1 и 2 я использую map и flatMap, чтобы проверить это поведение.одно из основных различий между ними заключается в map типе возвращаемого нормального значения, тогда как flatMap возвращает тип наблюдаемого.

В примерах 3 и 4 показано, что тип aaa и bbbObservable<String> ..

Теперь, когда в конце они становятся одним и тем же, зачем вам даже flatMap, чтобы вернуть определенный тип Observable?или зачем вам нужен map чтобы вернуть тип normal value?

(я знаю, что flatMap может делать другие вещи, это не является частью этой путаницы)

Ответы [ 2 ]

0 голосов
/ 03 февраля 2019

Они различаются несколькими способами.

  • map испускает только одно значение для каждого входящего в него значения.Принимая во внимание, что flatMap может выдавать одно или более значений для каждого входящего в него значения.

  • Закрытие, передаваемое карте, должно быть "чистым" (без стороныэффекты), в то время как закрытие, переданное flatMap, может иметь побочные эффекты (например, доступ к диску, доступ к пользовательскому интерфейсу и доступ к сети.) Да, поскольку Swift является нечистым языком, вы могли бы поместить побочные эффекты внутрь map но это нарушает договор.

Ответ Сандипа привел пример второго пункта, ниже пример первого пункта:

let string = Observable.of("a", "b", "c")

//Example 1
string
    .map { "\($0)-x" }
    .subscribe(onNext: { element in
        print(element) // only prints three values
    }, onCompleted: {
        print("completed")
    }
)

//Example 2
string
    .flatMap { Observable.of("\($0)-x", "\($0)-y", "\($0)-z") }
    .subscribe(onNext: { element in
        print(element) // this prints 9 values.
    }, onCompleted: {
        print("completed")
    }
)
0 голосов
/ 03 февраля 2019
Оператор

map используется для преобразования значения и передачи преобразованного значения следующему оператору, где flatmap выравнивает иерархию наблюдаемых и представляет ее как единственный оператор

Вариант использования для map и flatmap

Обычно вы используете map, если хотите преобразовать значение, полученное в текущем операторе, и передать его следующему оператору, как правило, синхронно.Например, в вашем случае, независимо от того, какое значение присвоено BehaviorRelay String, вы хотите вернуть "hhh", что является прямым синхронным преобразованием значения, поэтому map имеет смысл

string
    .map { _ in "hhh" }
    .subscribe(onNext: { element in
      print(element)
    }, onCompleted: {
      print("completed")
    }
  )

flatmapсгладить иерархию наблюдаемых и представить ее следующему оператору просто как одну наблюдаемую.Пример Предположим, что вы реализуете поиск, после того как значение сработало, вы хотите сделать вызов API и передать ответ следующему оператору.Теперь выполнение API-вызова является асинхронной операцией, и вы знаете, что простой map не будет проходить через него, тогда вы можете использовать flatmap

let string = BehaviorRelay<String>(value: "abcd")
    string
        .flatMap { s -> Observable<Response> in
            return Observable<Response>.create({ (observer) -> Disposable in
                //make api call here
                //pass data / error using observer.onNext or observer.onError()
                return Disposables.create()
            })
        }
        .subscribe(onNext: { element in
            print(element)
        }, onCompleted: {
            print("completed")
        }
    )

Так что здесь фактический API-вызов выполняется наблюдаемым внутри flatMapоператор, но для внешнего мира похоже, что BehaviorRelay сам преобразовал значение типа string в Response.

Это прекрасно, потому что не нужно знать все мелочи, связанные с вызовом API :)

Но, если честно, если вы действительно осуществляете поиск, вы бы предпочли flatMapLatestа не flatmap.Читайте больше на flatMap и flatMapLatest для лучшего понимания :)

...