问题
I searched for usage defer in Reactive, but still I don't understand why and when use the defer method.
As I understand all Observable method will not be fired until it subscribed, then, why we need to wrap the observable method with defer method?
Please advice me, and would be very appreciated if giving me with example.
[Updated]
Now I understood.
In reactive documentation, I saw this example,
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'); } );
And I was wondered,
why it wrapped Observable method with defer? How it will act differently?
回答1:
Quite simply, because Observables can encapsulate many different types of sources and those sources don't necessarily have to obey that interface. Some like Promises always attempt to eagerly compete.
Consider:
var promise = $.get('https://www.google.com');
The promise in this case is already executing before any handlers have been connected. If we want this to act more like an Observable then we need some way of deferring the creation of the promise until there is a subscription.
Hence we use defer to create a block that only gets executed when the resulting Observable is subscribed to.
Observable.defer(() => $.get('https://www.google.com'));
The above will not create the Promise until the Observable gets subscribed to and will thus behaves much more in line with the standard Observable interface.
回答2:
Take for example (From this article):
const source = Observable.defer(() => Observable.of(
Math.floor(Math.random() * 100)
));
Why don't just set the source Observable to of(Math.floor(Math.random() * 100)?
Because if we do that the expression Math.floor(Math.random() * 100) will run right away and be available in source as a value before we subscribe to source.
We want to delay the evaluation of the expression so we wrap of in defer. Now the expression Math.floor(Math.random() * 100) will be evaluated when source is subscribed to and not any time earlier.
We are wrapping of(...) in the defer factory function such that the construction of of(...) happens when the source observable is subscribed to.
回答3:
An example, let's say you want to send a request to a server. You have 2 options.
Via XmlHttpRequest
if you do not subscribe to an existing Observable Observable.create(fn) there would not be any network request. It sends the request only when you subscribe. This is normal and as it should be via Observables. Its the main beauty of it.
Via Promise (fetch, rx.fromPromise)
When you use Promises it does not work that way. Whether you subscribed or not, it sends the network requests right away. To fix this, you need to wrap promises in defer(fn).
回答4:
It would be easier to understand if we consider using dates.
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
For both observables (s1 and s2) we need to subscribe. But when s1 is subscribed, it will give the date-time at the moment when the constant was set. S2 will give the date-time at the moment of the subscription.
The code above was taken from https://www.learnrxjs.io/operators/creation/defer.html
来源:https://stackoverflow.com/questions/38764578/rxjs-understanding-defer