##// END OF EJS Templates
spelling fixes
andrei -
r25:35af87458b03 propose observables
parent child
Show More
1 NO CONTENT: file renamed from docs/cancellations.ru.md to docs/en/cancellations.md
@@ -1,85 +1,85
1 1 # Observable
2 2
3 3 Универсальный способ организации потока сообщений. Данный механизм может
4 4 использоваться для оповещения об изменениях состояний объектов или для доставки
5 5 самостоятельных событий, например, связанных с действиями пользователя.
6 6
7 7 Является реализацией классического шаблона наблюдателя с возможность сообщить
8 8 о коце потока событий. Данная реализация не содержит никаких дополнительных
9 9 функций, таких как фильтрация, канал с состоянием, преобразования сообщений и
10 10 т.п. Это сделано специально, чтобы реализация оставалась максимально простой.
11 11
12 12 Пример того, как можно создать последовательность из 10 событий:
13 13
14 14 ```ts
15 15 var events = new Observable(async (notify, error, complete) => {
16 16 // цикл в котором возникает событие
17 17 for(let i = 0; i < 10; i++) {
18 18 await delay(1000);
19 19 // в качестве данных передается номер события
20 20 notify(i);
21 21 }
22 22 // по окончании последовательности информируем, что событий больше не будет
23 23 compelte();
24 24 });
25 25
26 26 // создаем окно с отображением хода событий
27 27 var progress = showProgress({ min: 0, max: 9, current: 0});
28 28
29 29 // подписываемся на события
30 30 events.on(
31 31 // обработчик очередного события
32 32 msg => {
33 33 progress.setValue(msg);
34 }.
34 },
35 35 // обработчик ошибки
36 36 e => {
37 37 progress.showError(e);
38 38 },
39 39 // обработчик конца потока
40 40 () => {
41 41 progress.close();
42 42 }
43 43 );
44 44 ```
45 45
46 46 Пример создания `Observable` из событий другого объекта, например, виджета:
47 47
48 48 ```ts
49 49 postCreate() {
50 50 // превращаем события виджета в Observable
51 51 this.mouseMove = new Observable((notify) => {
52 52 this.moveArea.on('mousemove',(x) => notify(x.) );
53 53 });
54 54 }
55 55
56 56 ```
57 57
58 58 Пример инициализации `Observable` внутри класса и генерация событий:
59 59
60 60 ```ts
61 61
62 62 class PositionWidget extends Widget {
63 63 _nextPosition: (pos: Position) => void
64 64
65 65 _complete: () => void
66 66
67 67 readonly position: Observable<Position>;
68 68
69 69 constructor(...args[]) {
70 70 super(args);
71 71
72 72 this.position = new Observable<Position>((notify, error, complete) => {
73 73 this._nextPosition = notify;
74 74 this._complete = complete
75 75 });
76 76 }
77 77
78 78 destroy() {
79 79 this._complete();
80 80
81 81 super();
82 82 }
83 83 }
84 84
85 85 ``` No newline at end of file
1 NO CONTENT: file copied from docs/cancellations.ru.md to docs/ru/cancellations.md
@@ -1,85 +1,85
1 1 # Observable
2 2
3 3 Универсальный способ организации потока сообщений. Данный механизм может
4 4 использоваться для оповещения об изменениях состояний объектов или для доставки
5 5 самостоятельных событий, например, связанных с действиями пользователя.
6 6
7 7 Является реализацией классического шаблона наблюдателя с возможность сообщить
8 8 о коце потока событий. Данная реализация не содержит никаких дополнительных
9 9 функций, таких как фильтрация, канал с состоянием, преобразования сообщений и
10 10 т.п. Это сделано специально, чтобы реализация оставалась максимально простой.
11 11
12 12 Пример того, как можно создать последовательность из 10 событий:
13 13
14 14 ```ts
15 15 var events = new Observable(async (notify, error, complete) => {
16 16 // цикл в котором возникает событие
17 17 for(let i = 0; i < 10; i++) {
18 18 await delay(1000);
19 19 // в качестве данных передается номер события
20 20 notify(i);
21 21 }
22 22 // по окончании последовательности информируем, что событий больше не будет
23 23 compelte();
24 24 });
25 25
26 26 // создаем окно с отображением хода событий
27 27 var progress = showProgress({ min: 0, max: 9, current: 0});
28 28
29 29 // подписываемся на события
30 30 events.on(
31 31 // обработчик очередного события
32 32 msg => {
33 33 progress.setValue(msg);
34 }.
34 },
35 35 // обработчик ошибки
36 36 e => {
37 37 progress.showError(e);
38 38 },
39 39 // обработчик конца потока
40 40 () => {
41 41 progress.close();
42 42 }
43 43 );
44 44 ```
45 45
46 46 Пример создания `Observable` из событий другого объекта, например, виджета:
47 47
48 48 ```ts
49 49 postCreate() {
50 50 // превращаем события виджета в Observable
51 51 this.mouseMove = new Observable((notify) => {
52 52 this.moveArea.on('mousemove',(x) => notify(x.) );
53 53 });
54 54 }
55 55
56 56 ```
57 57
58 58 Пример инициализации `Observable` внутри класса и генерация событий:
59 59
60 60 ```ts
61 61
62 62 class PositionWidget extends Widget {
63 63 _nextPosition: (pos: Position) => void
64 64
65 65 _complete: () => void
66 66
67 67 readonly position: Observable<Position>;
68 68
69 69 constructor(...args[]) {
70 70 super(args);
71 71
72 72 this.position = new Observable<Position>((notify, error, complete) => {
73 73 this._nextPosition = notify;
74 74 this._complete = complete
75 75 });
76 76 }
77 77
78 78 destroy() {
79 79 this._complete();
80 80
81 81 super();
82 82 }
83 83 }
84 84
85 85 ``` No newline at end of file
@@ -1,193 +1,193
1 1 import { IObservable, IDestroyable, ICancellation } from './interfaces';
2 2 import { Cancellation } from './Cancellation'
3 3 import { argumentNotNull } from './safe';
4 4
5 5
6 6 interface Handler<T> {
7 7 (x: T): void
8 8 }
9 9
10 10 interface Initializer<T> {
11 11 (notify: Handler<T>, error?: (e: any) => void, complete?: () => void): void;
12 12 }
13 13
14 14 // TODO: think about to move this interfaces.ts and make it public
15 15 interface IObserver<T> {
16 16 next(event: T): void
17 17
18 18 error(e: any): void
19 19
20 20 complete(): void
21 21 }
22 22
23 23 const noop = () => {};
24 24
25 25 export class Observable<T> implements IObservable<T> {
26 26 private _once = new Array<IObserver<T>>();
27 27
28 28 private _observers = new Array<IObserver<T>>();
29 29
30 30
31 31 private _complete: boolean
32 32
33 33 private _error: any
34 34
35 35 constructor(func?: Initializer<T>) {
36 36 if (func)
37 37 func(
38 38 this._notifyNext.bind(this),
39 39 this._notifyError.bind(this),
40 40 this._notifyCompleted.bind(this)
41 41 );
42 42 }
43 43
44 44 /**
45 45 * Registers handlers for the current observable object.
46 46 *
47 47 * @param next the handler for events
48 48 * @param error the handler for a error
49 49 * @param complete the handler for a completion
50 50 * @returns {IDestroyable} the handler for the current subscription, this
51 51 * handler can be used to unsubscribe from events.
52 52 *
53 53 */
54 54 on(next: Handler<T>, error?: Handler<any>, complete?: () => void): IDestroyable {
55 55 argumentNotNull(next, "next");
56 56
57 57 let me = this;
58 58
59 59 let observer: IObserver<T> & IDestroyable = {
60 60 next: next,
61 61 error: error ? error.bind(null) : noop,
62 62 complete: complete ? complete.bind(null) : noop,
63 63
64 64 destroy() {
65 65 me._removeObserver(this);
66 66 }
67 }
67 };
68 68
69 69 this._addObserver(observer);
70 70
71 71
72 72 return observer;
73 73 }
74 74
75 75 private _addObserver(observer: IObserver<T>) {
76 76 if (this._complete) {
77 77 try {
78 78 if (this._error)
79 79 observer.error(this._error);
80 80 else
81 81 observer.complete();
82 82 } catch (e) {
83 83 this.onObserverException(e);
84 84 }
85 85 } else {
86 86 this._observers.push(observer);
87 87 }
88 88 }
89 89
90 90 /**
91 91 * Waits for the next event. This method can't be used to read messages
92 92 * as a sequence since it can skip some messages between calls.
93 93 *
94 94 * @param ct a cancellation token
95 95 */
96 96 next(ct: ICancellation = Cancellation.none): Promise<T> {
97 97 return new Promise<T>((resolve, reject) => {
98 98 let observer: IObserver<T> = {
99 99 next: resolve,
100 100 error: reject,
101 101 complete: () => reject("No more events are available")
102 102 };
103 103
104 104 if (this._addOnce(observer) && ct.isSupported()) {
105 105 ct.register((e) => {
106 106 this._removeOnce(observer);
107 107 reject(e);
108 108 });
109 109 }
110 110 });
111 111 }
112 112
113 113 private _addOnce(observer: IObserver<T>) {
114 114 if (this._complete) {
115 115 try {
116 116 if (this._error)
117 117 observer.error(this._error);
118 118 else
119 119 observer.complete();
120 120 } catch (e) {
121 121 this.onObserverException(e);
122 122 }
123 123 return false;
124 124 }
125 125
126 126 this._once.push(observer);
127 127 return true;
128 128 }
129 129
130 130 protected onObserverException(e: any) {
131 131 }
132 132
133 133 private _removeOnce(d: IObserver<T>) {
134 134 let i = this._once.indexOf(d);
135 135 if (i >= 0)
136 136 this._once.splice(i, 1);
137 137 }
138 138
139 139 private _removeObserver(d: IObserver<T>) {
140 140 let i = this._observers.indexOf(d);
141 141 if (i >= 0)
142 142 this._observers.splice(i, 1);
143 143 }
144 144
145 145 private _notify(guard: (observer: IObserver<T>) => void) {
146 146 if (this._once.length) {
147 147 for (let i = 0; i < this._once.length; i++)
148 148 guard(this._once[i]);
149 149 this._once = [];
150 150 }
151 151
152 152 for (let i = 0; i < this._observers.length; i++)
153 153 guard(this._observers[i]);
154 154 }
155 155
156 156 protected _notifyNext(evt: T) {
157 157 let guard = (observer: IObserver<T>) => {
158 158 try {
159 159 observer.next(evt);
160 160 } catch (e) {
161 161 this.onObserverException(e);
162 162 }
163 163 }
164 164
165 165 this._notify(guard);
166 166 }
167 167
168 168 protected _notifyError(e: any) {
169 169 let guard = (observer: IObserver<T>) => {
170 170 try {
171 171 observer.error(e);
172 172 } catch (e) {
173 173 this.onObserverException(e);
174 174 }
175 175 }
176 176
177 177 this._notify(guard);
178 178 this._observers = [];
179 179 }
180 180
181 181 protected _notifyCompleted() {
182 182 let guard = (observer: IObserver<T>) => {
183 183 try {
184 184 observer.complete();
185 185 } catch (e) {
186 186 this.onObserverException(e);
187 187 }
188 188 }
189 189
190 190 this._notify(guard);
191 191 this._observers = [];
192 192 }
193 193 } No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now