Rxjs, понимание отсрочки

Я искал использование defer в Reactive, но все же я не понимаю, почему и когда используется метод отсрочки.

Как я понимаю, весь метод Observable не будет запущен до его подписания, то почему нам нужно обернуть наблюдаемый метод методом отсрочки?

Пожалуйста, посоветуйте мне, и я был бы очень признателен, если бы дал мне пример.

[Обновлено]

Теперь я понял.

В реактивной документации я увидел этот пример,

var source = Rx.Observable.defer(function () {
    return Rx.Observable.return(42);
});

var subscription = source.subscribe(
    function (x) { console.log('Next: ' + x); },
    function (err) { console.log('Error: ' + err); },
    function () { console.log('Completed'); } );

И мне было интересно,

почему он обертывает метод Observable с отсрочкой? Как это будет действовать иначе?

Ответ 1

Проще говоря, поскольку Observables может инкапсулировать много разных типов источников, и эти источники необязательно должны подчиняться этому интерфейсу. Некоторым, вроде Promises, всегда хочется с жаром конкурировать.

Рассмотрим:

var promise = $.get('https://www.google.com');

Обещание в этом случае уже выполняется до того, как какие-либо обработчики подключены. Если мы хотим, чтобы это действовало скорее как Observable, тогда нам нужно каким-то образом отложить создание обещания до тех пор, пока не будет подписка.

Следовательно, мы используем defer для создания блока, который будет выполняться только при подписании результирующего Observable.

Observable.defer(() => $.get('https://www.google.com'));

Вышеуказанное не будет создавать Promise до тех пор, пока Observable не получит подписку и, таким образом, будет вести себя намного лучше в соответствии со стандартным интерфейсом Observable.

Ответ 2

Возьмем для примера (из этой статьи):

const source = Observable.defer(() => Observable.of(
  Math.floor(Math.random() * 100)
));

Почему бы просто не установить source Observable на of(Math.floor(Math.random() * 100)?

Потому что, если мы сделаем это, выражение Math.floor(Math.random() * 100) сразу же запустится и будет доступно в source как значение, прежде чем мы подпишемся на source.

Мы хотим отложить оценку выражения, поэтому заключаем of в defer. Теперь выражение Math.floor(Math.random() * 100) будет оцениваться при подписке на source, а не раньше.

Мы упаковываем of(...) в заводскую функцию defer так, что построение of(...) происходит, когда подписка на source подписана.

Ответ 3

Было бы легче понять, если мы рассмотрим использование дат.

const s1 = of(new Date()); //will capture current date time
const s2 = defer(() => of(new Date())); //will capture date time at the moment of subscription

Для обеих наблюдаемых (s1 и s2) нам нужно подписаться. Но когда подписка на s1 будет давать дату и время в тот момент, когда константа была установлена. S2 сообщит дату и время в момент подписки.

Код выше был взят из https://www.learnrxjs.io/operators/creation/defer.html

Ответ 4

Например, допустим, вы хотите отправить запрос на сервер. У вас есть 2 варианта.

Через XmlHttpRequest

если вы не subscribe к существующему Observable Observable.create(fn), не будет никакого сетевого запроса. Он отправляет запрос только, когда вы subscribe. Это нормально и так должно быть через Observables. Его главная красота.

Через обещание (fetch, rx.fromPromise)

Когда вы используете Обещания, это не работает таким образом. Независимо от того, подписаны вы или нет, он сразу отправляет сетевые запросы. Чтобы это исправить, вам нужно обернуть обещания в defer(fn).