1
1
# Operator Creation
2
2
3
- There are many ways to create an operator for RxJS. In this version of RxJS, performance was the primary consideration, as such, operator creation
4
- in a way that adheres to the existing structures in this library may not be straight forward. This is an attempt to document how to
3
+ There are many ways to create an operator for RxJS. In this version of RxJS, performance was the primary consideration, as such, operator creation
4
+ in a way that adheres to the existing structures in this library may not be straight forward. This is an attempt to document how to
5
5
create an operator either for yourself, or for this library.
6
6
7
7
For how to develop a custom operator for * this* library, [ see below] ( #advanced ) .
@@ -11,20 +11,20 @@ For how to develop a custom operator for *this* library, [see below](#advanced).
11
11
12
12
### Guidelines
13
13
14
- In the most common case, users might like to create an operator to be used only by their app. These can be developed in
14
+ In the most common case, users might like to create an operator to be used only by their app. These can be developed in
15
15
any way the developer sees fit, but here are some guidelines:
16
16
17
17
1 . __ Operators should always return an Observable__ . You're performing operations on unknown sets of things to create new sets.
18
18
It only makes sense to return a new set. If you create a method that returns something other than an Observable, it's not an operator,
19
19
and that's fine.
20
20
2 . __ Be sure to manage subscriptions__ created inside of the Observable your operator returns. Your operator is going to have to
21
- subscribe to the source (or ` this ` ) inside of the returned Observable, be sure that it's returned as part of unsubscribe handler or
21
+ subscribe to the source (or ` this ` ) inside of the returned Observable, be sure that it's returned as part of unsubscribe handler or
22
22
subscription.
23
- 3 . __ Be sure to handle exceptions from passed functions__ . If you're implementing an operator that takes a function as an argument,
23
+ 3 . __ Be sure to handle exceptions from passed functions__ . If you're implementing an operator that takes a function as an argument,
24
24
when you call it, you'll want to wrap it in a ` try/catch ` and send the error down the ` error() ` path on the observable.
25
25
4 . __ Be sure to teardown scarce resources__ in your unsubscribe handler of your returned Observable. If you're setting up event handlers
26
26
or a web socket, or something like that, the unsubscribe handler is a great place to remove that event handler or close that socket.
27
-
27
+
28
28
29
29
30
30
<!-- share-code-between-examples -->
@@ -36,7 +36,7 @@ function mySimpleOperator(someCallback) {
36
36
return Observable .create (subscriber => {
37
37
// because we're in an arrow function `this` is from the outer scope.
38
38
var source = this ;
39
-
39
+
40
40
// save our inner subscription
41
41
var subscription = source .subscribe (value => {
42
42
// important: catch errors from user-provided callbacks
@@ -45,12 +45,12 @@ function mySimpleOperator(someCallback) {
45
45
} catch (err) {
46
46
subscriber .error (err);
47
47
}
48
- },
48
+ },
49
49
// be sure to handle errors and completions as appropriate and
50
50
// send them along
51
51
err => subscriber .error (err),
52
52
() => subscriber .complete ());
53
-
53
+
54
54
// to return now
55
55
return subscription;
56
56
});
@@ -77,10 +77,10 @@ class MyObservable extends Observable {
77
77
observable .operator = operator;
78
78
return observable;
79
79
}
80
-
80
+
81
81
// put it here .. or ..
82
82
customOperator () {
83
- /* do things and return an Observable */
83
+ /* do things and return an Observable */
84
84
}
85
85
}
86
86
@@ -101,11 +101,11 @@ someObservable.mySimpleOperator(x => x + '!');
101
101
102
102
## <a id =" advanced " ></a >Creating An Operator For Inclusion In * This* Library
103
103
104
- __ To create an operator for inclusion in this library, it's probably best to work from prior art__ . Something
104
+ __ To create an operator for inclusion in this library, it's probably best to work from prior art__ . Something
105
105
like the ` filter ` operator would be a good start. It's not expected that you'll be able to read
106
106
this section and suddenly be an expert operator contributor.
107
107
108
- ** If you find yourself confused, DO NOT worry. Follow prior examples in the repo, submit a PR, and we'll work with you.**
108
+ ** If you find yourself confused, DO NOT worry. Follow prior examples in the repo, submit a PR, and we'll work with you.**
109
109
110
110
Hopefully the information provided here will give context to decisions made while developing operators in this library.
111
111
There are a few things to know and (try to) understand while developing operators:
@@ -114,15 +114,15 @@ There are a few things to know and (try to) understand while developing operator
114
114
"build their own observable" by pulling in operator methods an adding them to observable in their own module.
115
115
It also means operators can be brought in ad-hock and used directly, either with the ES7 function bind operator
116
116
in Babel (` :: ` ) or by using it with ` .call() ` .
117
- 2 . Every operator has an ` Operator ` class. The ` Operator ` class is really a ` Subscriber ` "factory". It's
118
- what gets passed into the ` lift ` method to make the "magic" happen. It's sole job is to create the operation's
117
+ 2 . Every operator has an ` Operator ` class. The ` Operator ` class is really a ` Subscriber ` "factory". It's
118
+ what gets passed into the ` lift ` method to make the "magic" happen. It's sole job is to create the operation's
119
119
` Subscriber ` instance on subscription.
120
- 3 . Every operator has a ` Subscriber ` class. This class does * all* of the logic for the operation. It's job is to
121
- handle values being nexted in (generally by overriding ` _next() ` ) and forward it along to the ` destination ` ,
120
+ 3 . Every operator has a ` Subscriber ` class. This class does * all* of the logic for the operation. It's job is to
121
+ handle values being nexted in (generally by overriding ` _next() ` ) and forward it along to the ` destination ` ,
122
122
which is the next observer in the chain.
123
123
- It's important to note that the ` destination ` Observer set on any ` Subscriber ` serves as more than just
124
124
the destinations for the events passing through, If the ` destination ` is a ` Subscriber ` it also is used to set up
125
- a shared underlying ` Subscription ` , which, in fact, is also a ` Subscriber ` , and is the first ` Subscriber ` in the
125
+ a shared underlying ` Subscription ` , which, in fact, is also a ` Subscriber ` , and is the first ` Subscriber ` in the
126
126
chain.
127
127
- Subscribers all have ` add ` and ` remove ` methods that are used for adding and removing inner subscriptions to
128
128
the shared underlying subscription.
@@ -133,7 +133,7 @@ There are a few things to know and (try to) understand while developing operator
133
133
134
134
Please complete these steps for each new operator added to RxJS as a pull request:
135
135
136
- - Add the operator to either Core or KitchenSink
136
+ - Add the operator to Rx
137
137
- It must have a ` -spec.ts ` tests file covering the canonical corner cases, with marble diagram tests
138
138
- If possible, write a ` asDiagram ` test case too, for PNG diagram generation purposes
139
139
- The spec file should have a type definition test at the end of the spec to verify type definition for various use cases
@@ -152,7 +152,7 @@ for their `unsubscribe` calls. Meaning if you call `unsubscribe` on them, it mig
152
152
not to set the ` destination ` of inner subscriptions. An example of this might be the switch operators, that have a single underlying
153
153
inner subscription that needs to unsubscribe independent of the main subscription.
154
154
155
- If you find yourself creating inner subscriptions, it might also be worth checking to see if the observable being passed ` _isScalar ` ,
155
+ If you find yourself creating inner subscriptions, it might also be worth checking to see if the observable being passed ` _isScalar ` ,
156
156
because if it is, you can pull the ` value ` out of it directly and improve the performance of your operator when it's operating over
157
157
scalar observables. For reference a scalar observable is any observable that has a single static value underneath it. ` Observable.of('foo') ` will
158
158
return a ` ScalarObservable ` , likewise, resolved ` PromiseObservable ` s will act as scalars.
0 commit comments