Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(docs-infra): convert hard-coded comparing-observables examples into a proper mini-app #34327

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Expand Up @@ -867,6 +867,7 @@ testing/** @angular/fw-test
/aio/content/guide/observables.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/observables/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/comparing-observables.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/comparing-observables/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/observables-in-angular.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/examples/observables-in-angular/** @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
/aio/content/guide/practical-observable-usage.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes
Expand Down
40 changes: 40 additions & 0 deletions aio/content/examples/comparing-observables/src/observables.ts
@@ -0,0 +1,40 @@
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs';

// #docregion observable

// declare a publishing operation
const observable = new Observable<number>(observer => {
// Subscriber fn...
});

// initiate execution
observable.subscribe(() => {
// observer handles notifications
});

// #enddocregion observable

// #docregion unsubscribe

const subscription = observable.subscribe(() => {
// observer handles notifications
});
gkalpak marked this conversation as resolved.
Show resolved Hide resolved

subscription.unsubscribe();

// #enddocregion unsubscribe

// #docregion error

observable.subscribe(() => {
throw Error('my error');
});

// #enddocregion error

// #docregion chain

observable.pipe(map(v => 2 * v));

// #enddocregion chain
25 changes: 25 additions & 0 deletions aio/content/examples/comparing-observables/src/promises.ts
@@ -0,0 +1,25 @@
// #docregion promise
// initiate execution
const promise = new Promise<number>((resolve, reject) => {
// Executer fn...
});

promise.then(value => {
// handle result here
});

// #enddocregion promise

// #docregion chain

promise.then(v => 2 * v);

// #enddocregion chain

// #docregion error

promise.then(() => {
throw Error('my error');
});

// #enddocregion error
100 changes: 51 additions & 49 deletions aio/content/guide/comparing-observables.md
Expand Up @@ -21,68 +21,67 @@ Observables are often compared to promises. Here are some key differences:

* Observables are not executed until a consumer subscribes. The `subscribe()` executes the defined behavior once, and it can be called again. Each subscription has its own computation. Resubscription causes recomputation of values.

<code-example hideCopy>
// declare a publishing operation
new Observable((observer) => { subscriber_fn });
// initiate execution
observable.subscribe(() => {
// observer handles notifications
});
</code-example>
<code-example
path="comparing-observables/src/observables.ts"
header="src/observables.ts (observable)"
region="observable">
</code-example>

* Promises execute immediately, and just once. The computation of the result is initiated when the promise is created. There is no way to restart work. All `then` clauses (subscriptions) share the same computation.

<code-example hideCopy>
// initiate execution
new Promise((resolve, reject) => { executer_fn });
// handle return value
promise.then((value) => {
// handle result here
});
</code-example>
<code-example
path="comparing-observables/src/promises.ts"
header="src/promises.ts (promise)"
region="promise">
</code-example>

### Chaining

* Observables differentiate between transformation function such as a map and subscription. Only subscription activates the subscriber function to start computing the values.


<code-example hideCopy>observable.pipe(map((v) => 2*v));</code-example>

<code-example
path="comparing-observables/src/observables.ts"
header="src/observables.ts (chain)"
region="chain">
</code-example>

* Promises do not differentiate between the last `.then` clauses (equivalent to subscription) and intermediate `.then` clauses (equivalent to map).


<code-example hideCopy>promise.then((v) => 2*v);</code-example>

<code-example
path="comparing-observables/src/promises.ts"
header="src/promises.ts (chain)"
region="chain">
</code-example>

### Cancellation

* Observable subscriptions are cancellable. Unsubscribing removes the listener from receiving further values, and notifies the subscriber function to cancel work.

<code-example hideCopy>
const sub = obs.subscribe(...);
sub.unsubscribe();
</code-example>
<code-example
path="comparing-observables/src/observables.ts"
header="src/observables.ts (unsubcribe)"
region="unsubscribe">
</code-example>

gkalpak marked this conversation as resolved.
Show resolved Hide resolved
* Promises are not cancellable.

### Error handling

* Observable execution errors are delivered to the subscriber's error handler, and the subscriber automatically unsubscribes from the observable.

<code-example hideCopy>
obs.subscribe(() => {
throw Error('my error');
});
</code-example>
<code-example
path="comparing-observables/src/observables.ts"
header="src/observables.ts (error)"
region="error">
</code-example>

* Promises push errors to the child promises.

<code-example hideCopy>
promise.then(() => {
throw Error('my error');
});
</code-example>
<code-example
path="comparing-observables/src/promises.ts"
header="src/promises.ts (error)"
region="error">
</code-example>

### Cheat sheet

Expand All @@ -100,14 +99,16 @@ The following code snippets illustrate how the same kind of operation is defined
<tr>
<td>Creation</td>
<td>
<pre>new Observable((observer) => {
gkalpak marked this conversation as resolved.
Show resolved Hide resolved
observer.next(123);
});</pre>
<pre>
new Observable((observer) => {
observer.next(123);
});</pre>
</td>
<td>
<pre>new Promise((resolve, reject) => {
resolve(123);
});</pre>
<pre>
new Promise((resolve, reject) => {
resolve(123);
});</pre>
</td>
</tr>
<tr>
Expand All @@ -118,14 +119,16 @@ The following code snippets illustrate how the same kind of operation is defined
<tr>
<td>Subscribe</td>
<td>
<pre>sub = obs.subscribe((value) => {
console.log(value)
});</pre>
<pre>
sub = obs.subscribe((value) => {
console.log(value)
});</pre>
</td>
<td>
<pre>promise.then((value) => {
console.log(value);
});</pre>
<pre>
promise.then((value) => {
console.log(value);
});</pre>
</td>
</tr>
<tr>
Expand Down Expand Up @@ -165,7 +168,6 @@ subscription.unsubscribe();</pre>
<pre>function handler(e) {
console.log(‘Clicked’, e);
}

gkalpak marked this conversation as resolved.
Show resolved Hide resolved
gkalpak marked this conversation as resolved.
Show resolved Hide resolved
// Setup & begin listening
button.addEventListener(‘click’, handler);
// Stop listening
Expand Down