Skip to content

Commit

Permalink
Spec the catch() operator (#172)
Browse files Browse the repository at this point in the history
  • Loading branch information
domfarolino authored Aug 28, 2024
1 parent 69ad0de commit 35be035
Showing 1 changed file with 75 additions and 0 deletions.
75 changes: 75 additions & 0 deletions spec.bs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,10 @@ callback Mapper = any (any value, unsigned long long index);
// used to visit each element in a sequence, not transform it.
callback Visitor = undefined (any value, unsigned long long index);

// This callback returns an `any` that must convert into an `Observable`, via
// the `Observable` conversion semantics.
callback CatchCallback = any (any value);

[Exposed=*]
interface Observable {
constructor(SubscribeCallback callback);
Expand All @@ -375,6 +379,7 @@ interface Observable {
Observable flatMap(Mapper mapper);
Observable switchMap(Mapper mapper);
Observable inspect(optional ObservableInspectorUnion inspect_observer = {});
Observable catch(CatchCallback callback);
Observable finally(VoidFunction callback);

// Promise-returning operators.
Expand Down Expand Up @@ -1207,6 +1212,76 @@ For now, see [https://github.com/wicg/observable#operators](https://github.com/w
</wpt>
</div>

<div algorithm>
The <dfn for=Observable method><code>catch(|callback|)</code></dfn> method steps are:

1. Let |sourceObservable| be [=this=].

1. Let |observable| be a [=new=] {{Observable}} whose [=Observable/subscribe callback=] is an
algorithm that takes a {{Subscriber}} |subscriber| and does the following:

1. Let |sourceObserver| be a new [=internal observer=], initialized as follows:

: [=internal observer/next steps=]
:: Run |subscriber|'s {{Subscriber/next()}} method, given the passed in <var
ignore>value</var>.

: [=internal observer/error steps=]
::
1. [=Invoke=] |callback| with the passed in <var ignore>error</var>. Let |result| be
the returned value.

If <a spec=webidl lt="an exception was thrown">an exception |E| was thrown</a>, then
run |subscriber|'s {{Subscriber/error()}} with |E|, and abort these steps.

1. Let |innerObservable| be the result of calling {{Observable/from()}} with |result|.

If <a spec=webidl lt="an exception was thrown">an exception |E| was thrown</a>, then
run |subscriber|'s {{Subscriber/error()}} method, given |E|, and abort these steps.

Issue: We shouldn't invoke {{Observable/from()}} directly. Rather, we should
call some internal algorithm that passes-back the exceptions for us to handle
properly here, since we want to pipe them to |subscriber|.

1. Let |innerObserver| be a new [=internal observer=], initialized as follows:

: [=internal observer/next steps=]
:: Run |subscriber|'s {{Subscriber/next()}} method, given the passed in <var
ignore>value</var>.

: [=internal observer/error steps=]
:: Run |subscriber|'s {{Subscriber/error()}} method, given the passed in <var
ignore>error</var>.

: [=internal observer/complete steps=]
:: Run |subscriber|'s {{Subscriber/complete()}} method.

1. Let |innerOptions| be a new {{SubscribeOptions}} whose {{SubscribeOptions/signal}}
is |subscriber|'s [=Subscriber/subscription controller=]'s
[=AbortController/signal=].

1. <a for=Observable lt="subscribe to an Observable">Subscribe</a> to |innerObservable|
given |innerObserver| and |innerOptions|.

Note: We're free to subscribe to |innerObservable| here without first
"unsubscribing" from |sourceObservable|, and without fear that |sourceObservable|
will keep emitting values, because all of this is happening inside of the [=internal
observer/error steps=] associated with |sourceObservable|. This means
|sourceObservable| has already completed its subscription and will no longer produce
any values, and we are free to safely switch our source of values to |innerObservable|.

: [=internal observer/complete steps=]
:: Run |subscriber|'s {{Subscriber/complete()}} method.

1. Let |options| be a new {{SubscribeOptions}} whose {{SubscribeOptions/signal}} is
|subscriber|'s [=Subscriber/subscription controller=]'s [=AbortController/signal=].

1. <a for=Observable lt="subscribe to an Observable">Subscribe</a> to |sourceObservable|
given |sourceObserver| and |options|.

1. Return |observable|.
</div>

<div algorithm>
The <dfn for=Observable method><code>finally(|callback|)</code></dfn> method steps are:

Expand Down

0 comments on commit 35be035

Please sign in to comment.