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

Previously, the examples in the `comparing-observables` guide were hard-coded.
This made it impossible to test them and verify they are correct.

This commit fixes this by converting them into a proper mini-app. In a
subsequent commit, tests will be added to verify that the source code
works as expected (and guard against regressions).

Fixes #31024

PR Close #34327
This commit is contained in:
Sonu Kapoor 2019-12-10 09:34:32 -05:00 committed by Matias Niemelä
parent 7342d4b6f0
commit def4127bf1
4 changed files with 117 additions and 49 deletions

1
.github/CODEOWNERS vendored
View File

@ -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/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/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/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/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/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 /aio/content/guide/practical-observable-usage.md @angular/fw-docs-observables @angular/framework-global-approvers @angular/framework-global-approvers-for-docs-only-changes

View File

@ -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
});
subscription.unsubscribe();
// #enddocregion unsubscribe
// #docregion error
observable.subscribe(() => {
throw Error('my error');
});
// #enddocregion error
// #docregion chain
observable.pipe(map(v => 2 * v));
// #enddocregion chain

View File

@ -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

View File

@ -21,48 +21,47 @@ 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. * 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> <code-example
// declare a publishing operation path="comparing-observables/src/observables.ts"
new Observable((observer) => { subscriber_fn }); header="src/observables.ts (observable)"
// initiate execution region="observable">
observable.subscribe(() => { </code-example>
// observer handles notifications
});
</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. * 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> <code-example
// initiate execution path="comparing-observables/src/promises.ts"
new Promise((resolve, reject) => { executer_fn }); header="src/promises.ts (promise)"
// handle return value region="promise">
promise.then((value) => { </code-example>
// handle result here
});
</code-example>
### Chaining ### Chaining
* Observables differentiate between transformation function such as a map and subscription. Only subscription activates the subscriber function to start computing the values. * Observables differentiate between transformation function such as a map and subscription. Only subscription activates the subscriber function to start computing the values.
<code-example
<code-example hideCopy>observable.pipe(map((v) => 2*v));</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). * Promises do not differentiate between the last `.then` clauses (equivalent to subscription) and intermediate `.then` clauses (equivalent to map).
<code-example
<code-example hideCopy>promise.then((v) => 2*v);</code-example> path="comparing-observables/src/promises.ts"
header="src/promises.ts (chain)"
region="chain">
</code-example>
### Cancellation ### Cancellation
* Observable subscriptions are cancellable. Unsubscribing removes the listener from receiving further values, and notifies the subscriber function to cancel work. * Observable subscriptions are cancellable. Unsubscribing removes the listener from receiving further values, and notifies the subscriber function to cancel work.
<code-example hideCopy> <code-example
const sub = obs.subscribe(...); path="comparing-observables/src/observables.ts"
sub.unsubscribe(); header="src/observables.ts (unsubcribe)"
</code-example> region="unsubscribe">
</code-example>
* Promises are not cancellable. * Promises are not cancellable.
@ -70,19 +69,19 @@ sub.unsubscribe();
* Observable execution errors are delivered to the subscriber's error handler, and the subscriber automatically unsubscribes from the observable. * Observable execution errors are delivered to the subscriber's error handler, and the subscriber automatically unsubscribes from the observable.
<code-example hideCopy> <code-example
obs.subscribe(() => { path="comparing-observables/src/observables.ts"
throw Error('my error'); header="src/observables.ts (error)"
}); region="error">
</code-example> </code-example>
* Promises push errors to the child promises. * Promises push errors to the child promises.
<code-example hideCopy> <code-example
promise.then(() => { path="comparing-observables/src/promises.ts"
throw Error('my error'); header="src/promises.ts (error)"
}); region="error">
</code-example> </code-example>
### Cheat sheet ### Cheat sheet
@ -100,14 +99,16 @@ The following code snippets illustrate how the same kind of operation is defined
<tr> <tr>
<td>Creation</td> <td>Creation</td>
<td> <td>
<pre>new Observable((observer) => { <pre>
observer.next(123); new Observable((observer) => {
});</pre> observer.next(123);
});</pre>
</td> </td>
<td> <td>
<pre>new Promise((resolve, reject) => { <pre>
resolve(123); new Promise((resolve, reject) => {
});</pre> resolve(123);
});</pre>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -118,14 +119,16 @@ The following code snippets illustrate how the same kind of operation is defined
<tr> <tr>
<td>Subscribe</td> <td>Subscribe</td>
<td> <td>
<pre>sub = obs.subscribe((value) => { <pre>
console.log(value) sub = obs.subscribe((value) => {
});</pre> console.log(value)
});</pre>
</td> </td>
<td> <td>
<pre>promise.then((value) => { <pre>
console.log(value); promise.then((value) => {
});</pre> console.log(value);
});</pre>
</td> </td>
</tr> </tr>
<tr> <tr>
@ -165,7 +168,6 @@ subscription.unsubscribe();</pre>
<pre>function handler(e) { <pre>function handler(e) {
console.log(Clicked, e); console.log(Clicked, e);
} }
// Setup & begin listening // Setup & begin listening
button.addEventListener(click, handler); button.addEventListener(click, handler);
// Stop listening // Stop listening