BACK
Lessons9. defer: a factory on every subscription
Lessons · 09

9. defer: a factory on every subscription

The problem: the value depends on when you subscribe

Picture this: you want an Observable that returns the current time. Write of(Date.now()) and the time "freezes" at the moment the Observable is created. Every subscriber gets the same value — even one that subscribes an hour later.

The fix: defer

defer(factory) takes a factory function. It's called afresh every time someone subscribes. Inside, you can compute an up-to-date value or build a brand-new Observable.

defer(() => of(Date.now()))
// Every subscriber gets a fresh Date.now()

Where it's useful

  • The current date, or an up-to-date auth token.
  • A fresh HTTP request: re-subscribing should fire a new request, not replay a cached one.
  • Any value that should be computed at subscription time, not at creation time.

Glossary

  • Factory — a function that builds something new on demand. In defer, it builds an Observable.

Your task

  1. Inside the factory function, make the first line bump the counter: calls++;.
  2. Log console.log('Factory call: ' + calls).
  3. Instead of of('TODO'), return of('Data ' + calls) so the value depends on the call number.
  4. Expected order: Sub A → Factory call: 1 → Data 1 → Sub B → Factory call: 2 → Data 2. Two subscribers — two independent runs.
Solution spoiler · click to reveal
const { defer, of } = Rx;

let calls = 0;

const request$ = defer(() => {
  calls++;
  console.log('Factory call: ' + calls);
  return of('Data ' + calls);
});

console.log('Sub A');
request$.subscribe(value => console.log(value));

console.log('Sub B');
request$.subscribe(value => console.log(value));
script.ts // TypeScript
CONSOLE · Console output
Hit Run to see the result...