##// END OF EJS Templates
working on Observable tests
cin -
r24:70558f9420b3 propose observables
parent child
Show More
@@ -0,0 +1,36
1 import { TraceSource, DebugLevel } from '@implab/core/log/TraceSource'
2 import * as tape from 'tape';
3 import { TapeWriter, delay } from './TestTraits';
4 import { Observable } from '@implab/core/Observable';
5 import { IObservable } from '@implab/core/interfaces';
6
7 let trace = TraceSource.get("ObservableTests");
8
9 tape('events sequence example', async t => {
10
11
12 let events: IObservable<number>
13
14 let done = new Promise<void>((resolve) => {
15 events = new Observable<number>(async (notify, fail, complete) => {
16 for (let i = 0; i < 10; i++) {
17 await delay(0);
18 notify(i);
19 }
20 resolve();
21 });
22 });
23
24 let count = 0;
25 events.on(x => count = count + x);
26
27 let first = await events.next();
28
29 t.equals(first, 0, "the first event");
30
31 await done;
32
33 t.equals(count, 45, "the summ of the evetns");
34
35 t.end();
36 }); No newline at end of file
@@ -41,55 +41,40 events.on(
41 progress.close();
41 progress.close();
42 }
42 }
43 );
43 );
44
45 // ожидание следующего события
46 let firstEvent = await events.next();
47 ```
44 ```
48
45
49 `Observable` можно создавать из событий другого объекта, например, виджета:
46 Пример создания `Observable` из событий другого объекта, например, виджета:
50
47
51 ```ts
48 ```ts
52 // клсс
49 postCreate() {
53 class Canvas {
50 // превращаем события виджета в Observable
54 readonly mouseMove: IObservable<[number,number]>
51 this.mouseMove = new Observable((notify) => {
55
52 this.moveArea.on('mousemove',(x) => notify(x.) );
56 postCreate() {
53 });
57 // превращаем события виджета в Observable
58 this.mouseMove = new Observable<[number,number]>((notify) => {
59 this.mousePad.on('mousemove',(e) => notify([e.clientX, e.clientY]) );
60 });
61 }
62 }
54 }
63
55
64 ```
56 ```
65
57
66 Если объект инкапсулирует в себе `Observable`, он также может сохранить методы
58 Пример инициализации `Observable` внутри класса и генерация событий:
67 для оповещения подписчиков для дальнейшего их использования внутри класса.
68
59
69 ```ts
60 ```ts
70 // класс, который будет генерировать события местоположения
61
71 class PositionTracker implements IDestroyable {
62 class PositionWidget extends Widget {
72 // _nextPosition и _complete будут связаны с position при создании
73 // экземпляра PositionTracker.
74 _nextPosition: (pos: Position) => void
63 _nextPosition: (pos: Position) => void
64
75 _complete: () => void
65 _complete: () => void
76
66
77 readonly position: IObservable<Position>
67 readonly position: Observable<Position>;
78
68
79 // конструктор
69 constructor(...args[]) {
80 constructor(...args: any[]) {
81 super(args);
70 super(args);
82
71
83 // создаем Observable
84 this.position = new Observable<Position>((notify, error, complete) => {
72 this.position = new Observable<Position>((notify, error, complete) => {
85 // сохраняем методы для оповещения о новом местоположении
86 this._nextPosition = notify;
73 this._nextPosition = notify;
87 // метод об оповещении конца потока событий
88 this._complete = complete
74 this._complete = complete
89 });
75 });
90 }
76 }
91
77
92 // метод для очистки ресурсов
93 destroy() {
78 destroy() {
94 this._complete();
79 this._complete();
95
80
@@ -97,39 +82,4 class PositionTracker implements IDestro
97 }
82 }
98 }
83 }
99
84
100 ```
101
102 ## Observable и последовательности
103
104 Можно сичтать, что `Observable` это некоторая аналогия итератора только в
105 парадигме событийного (или реактивного) программировния. Следует также понимать,
106 что при переходе от синхронного процедурного программирования к событийному так
107 же меняется и направление управления (Inverse Of Control), что означает
108 следующее:
109
110 * при работе с итераторами клиенты сами определяют момент чтения следующего
111 элемента последовательности.
112 * при работе с `Observable` клиенты вынуждены обрабатывать эти события по мере
113 их поступления и не могут на это повлиять.
114
115 Последний пункт можно изменить применив, например, буффер или канал с
116 состоянием, т.е. очередь, но данные механизмы выходят за рамки простого шаблона
117 наблюдателя.
118
119 ```ts
120 while(1) {
121 // ожидаем следующее событие, по сути это подписка только на одно событие
122 let next = await events.next();
123
124 // такой цикл может пропускать сообщения, поскольку асинхронная операция
125 // позволит возобновить создание новых событий, на которые мы не подписаны
126 await processEvent(next);
127
128 // не только асинхронные операции могут привести к пропуску события
129 // например вызов метода, который приводит к созданию события так же
130 // приведет к тому, что созданное событие не будет обработано в текущем
131 // цикле
132 doSmthAndRiseEvent();
133 }
134
135 ``` No newline at end of file
85 ```
@@ -1,2 +1,3
1 define(["./ActivatableTests", "./trace-test", "./TraceSourceTests", "./CancellationTests"]);
1 //define(["./ActivatableTests", "./trace-test", "./TraceSourceTests", "./CancellationTests"]);
2 //define(["./CancellationTests"]); No newline at end of file
2 //define(["./CancellationTests"]);
3 define(["./ObservableTests"]); No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now