@guanghechen/observable 6.1.7 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
@@ -0,0 +1,154 @@
1
+ <header>
2
+ <h1 align="center">
3
+ <a href="https://github.com/guanghechen/sora/tree/@guanghechen/observable@7.0.0/packages/observable#readme">@guanghechen/observable</a>
4
+ </h1>
5
+ <div align="center">
6
+ <a href="https://www.npmjs.com/package/@guanghechen/observable">
7
+ <img
8
+ alt="Npm Version"
9
+ src="https://img.shields.io/npm/v/@guanghechen/observable.svg"
10
+ />
11
+ </a>
12
+ <a href="https://www.npmjs.com/package/@guanghechen/observable">
13
+ <img
14
+ alt="Npm Download"
15
+ src="https://img.shields.io/npm/dm/@guanghechen/observable.svg"
16
+ />
17
+ </a>
18
+ <a href="https://www.npmjs.com/package/@guanghechen/observable">
19
+ <img
20
+ alt="Npm License"
21
+ src="https://img.shields.io/npm/l/@guanghechen/observable.svg"
22
+ />
23
+ </a>
24
+ <a href="#install">
25
+ <img
26
+ alt="Module Formats: cjs, esm"
27
+ src="https://img.shields.io/badge/module_formats-cjs%2C%20esm-green.svg"
28
+ />
29
+ </a>
30
+ <a href="https://github.com/nodejs/node">
31
+ <img
32
+ alt="Node.js Version"
33
+ src="https://img.shields.io/node/v/@guanghechen/observable"
34
+ />
35
+ </a>
36
+ <a href="https://github.com/facebook/jest">
37
+ <img
38
+ alt="Tested with Jest"
39
+ src="https://img.shields.io/badge/tested_with-jest-9c465e.svg"
40
+ />
41
+ </a>
42
+ <a href="https://github.com/prettier/prettier">
43
+ <img
44
+ alt="Code Style: prettier"
45
+ src="https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square"
46
+ />
47
+ </a>
48
+ </div>
49
+ </header>
50
+ <br/>
51
+
52
+ Observable pattern implementation with ticker functionality for reactive programming.
53
+
54
+ ## Install
55
+
56
+ - npm
57
+
58
+ ```bash
59
+ npm install --save @guanghechen/observable
60
+ ```
61
+
62
+ - yarn
63
+
64
+ ```bash
65
+ yarn add @guanghechen/observable
66
+ ```
67
+
68
+ ## Usage
69
+
70
+ | Name | Description |
71
+ | :--------------: | :-------------------------------------------------------: |
72
+ | `Observable` | Reactive observable value with change notification |
73
+ | `Ticker` | Timer-based ticker for scheduled notifications |
74
+
75
+ ## Example
76
+
77
+ - Basic observable:
78
+
79
+ ```typescript
80
+ import { Observable } from '@guanghechen/observable'
81
+ import { Subscriber } from '@guanghechen/subscriber'
82
+
83
+ const observable = new Observable<number>(0)
84
+
85
+ // Create a subscriber
86
+ const subscriber = new Subscriber({
87
+ onNext: (newValue, oldValue) => {
88
+ console.log(`Value changed from ${oldValue} to ${newValue}`)
89
+ },
90
+ onDispose: () => {
91
+ console.log('Subscriber disposed')
92
+ }
93
+ })
94
+
95
+ // Subscribe to changes
96
+ const unsubscribe = observable.subscribe(subscriber)
97
+
98
+ observable.next(1) // Output: "Value changed from undefined to 1"
99
+ observable.next(2) // Output: "Value changed from 1 to 2"
100
+
101
+ unsubscribe.unsubscribe()
102
+ ```
103
+
104
+ - Observable with custom equality:
105
+
106
+ ```typescript
107
+ import { Observable } from '@guanghechen/observable'
108
+ import { Subscriber } from '@guanghechen/subscriber'
109
+
110
+ const observable = new Observable<{id: number, name: string}>(
111
+ { id: 1, name: 'John' },
112
+ { equals: (a, b) => a.id === b.id }
113
+ )
114
+
115
+ const subscriber = new Subscriber({
116
+ onNext: (newVal) => {
117
+ console.log('Object changed:', newVal)
118
+ }
119
+ })
120
+
121
+ observable.subscribe(subscriber)
122
+
123
+ // This won't trigger notification (same id)
124
+ observable.next({ id: 1, name: 'Jane' })
125
+
126
+ // This will trigger notification (different id)
127
+ observable.next({ id: 2, name: 'Bob' })
128
+ ```
129
+
130
+ - Using ticker:
131
+
132
+ ```typescript
133
+ import { Ticker } from '@guanghechen/observable'
134
+ import { Subscriber } from '@guanghechen/subscriber'
135
+
136
+ const ticker = new Ticker<string>('initial', { interval: 1000 })
137
+
138
+ const subscriber = new Subscriber({
139
+ onNext: (value) => {
140
+ console.log('Ticker value:', value)
141
+ }
142
+ })
143
+
144
+ ticker.subscribe(subscriber)
145
+ ticker.start()
146
+
147
+ // Update ticker value
148
+ setTimeout(() => {
149
+ ticker.next('updated value')
150
+ }, 2000)
151
+ ```
152
+
153
+ [homepage]:
154
+ https://github.com/guanghechen/sora/tree/@guanghechen/observable@7.0.0/packages/observable#readme
package/lib/cjs/index.cjs CHANGED
@@ -42,6 +42,10 @@ class Observable extends disposable.BatchDisposable {
42
42
  dispose() {
43
43
  if (this.disposed)
44
44
  return;
45
+ if (this._timer !== undefined) {
46
+ clearTimeout(this._timer);
47
+ this._timer = undefined;
48
+ }
45
49
  super.dispose();
46
50
  this._flush();
47
51
  this._subscribers.dispose();
@@ -96,12 +100,19 @@ class Observable extends disposable.BatchDisposable {
96
100
  if (this._timer === undefined) {
97
101
  this._timer = setTimeout(() => {
98
102
  try {
99
- this._notifyImmediate();
103
+ if (!this.disposed) {
104
+ this._notifyImmediate();
105
+ }
106
+ }
107
+ catch (error) {
108
+ console.error('Error in observable notification:', error);
100
109
  }
101
110
  finally {
102
111
  this._timer = undefined;
103
112
  }
104
- this._notify();
113
+ if (!this.disposed) {
114
+ this._notify();
115
+ }
105
116
  }, this._delay);
106
117
  }
107
118
  }
package/lib/esm/index.mjs CHANGED
@@ -40,6 +40,10 @@ class Observable extends BatchDisposable {
40
40
  dispose() {
41
41
  if (this.disposed)
42
42
  return;
43
+ if (this._timer !== undefined) {
44
+ clearTimeout(this._timer);
45
+ this._timer = undefined;
46
+ }
43
47
  super.dispose();
44
48
  this._flush();
45
49
  this._subscribers.dispose();
@@ -94,12 +98,19 @@ class Observable extends BatchDisposable {
94
98
  if (this._timer === undefined) {
95
99
  this._timer = setTimeout(() => {
96
100
  try {
97
- this._notifyImmediate();
101
+ if (!this.disposed) {
102
+ this._notifyImmediate();
103
+ }
104
+ }
105
+ catch (error) {
106
+ console.error('Error in observable notification:', error);
98
107
  }
99
108
  finally {
100
109
  this._timer = undefined;
101
110
  }
102
- this._notify();
111
+ if (!this.disposed) {
112
+ this._notify();
113
+ }
103
114
  }, this._delay);
104
115
  }
105
116
  }
@@ -99,7 +99,7 @@ interface ITicker extends IObservable<number> {
99
99
  * @param observable
100
100
  * @param options
101
101
  */
102
- observe(observable: IBaseObservable<any>, options?: ITickerObserveOptions): void;
102
+ observe(observable: IBaseObservable<any>, options?: ITickerObserveOptions): IUnobservable;
103
103
  }
104
104
 
105
105
  declare class Ticker extends Observable<number> implements ITicker {
@@ -113,4 +113,5 @@ declare const noopUnsubscribable: IUnsubscribable;
113
113
  declare const noopUnobservable: IUnobservable;
114
114
  declare const isObservable: (obj: unknown) => obj is IObservable<unknown>;
115
115
 
116
- export { type IBaseObservable, type IEquals, type IObservable, type IObservableKey, type IObservableNextOptions, type IObservableOptions, type IObservableRecord, type ITicker, type ITickerObserveOptions, type ITickerOptions, type IUnobservable, type IValueList, type IValueMap, Observable, Ticker, isObservable, noop, noopUnobservable, noopUnsubscribable };
116
+ export { Observable, Ticker, isObservable, noop, noopUnobservable, noopUnsubscribable };
117
+ export type { IBaseObservable, IEquals, IObservable, IObservableKey, IObservableNextOptions, IObservableOptions, IObservableRecord, ITicker, ITickerObserveOptions, ITickerOptions, IUnobservable, IValueList, IValueMap };
package/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@guanghechen/observable",
3
- "version": "6.1.7",
3
+ "version": "7.0.0",
4
4
  "author": {
5
5
  "name": "guanghechen",
6
6
  "url": "https://github.com/guanghechen/"
7
7
  },
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "https://github.com/guanghechen/sora/tree/@guanghechen/observable@6.1.6",
10
+ "url": "https://github.com/guanghechen/sora/tree/@guanghechen/observable@6.1.8",
11
11
  "directory": "packages/observable"
12
12
  },
13
- "homepage": "https://github.com/guanghechen/sora/tree/@guanghechen/observable@6.1.6/packages/observable#readme",
13
+ "homepage": "https://github.com/guanghechen/sora/tree/@guanghechen/observable@6.1.8/packages/observable#readme",
14
14
  "keywords": [
15
15
  "observable"
16
16
  ],
@@ -25,6 +25,13 @@
25
25
  "module": "./lib/esm/index.mjs",
26
26
  "source": "./src/index.ts",
27
27
  "license": "MIT",
28
+ "scripts": {
29
+ "build": "rollup -c ../../rollup.config.mjs",
30
+ "clean": "rimraf lib",
31
+ "test": "vitest run --config ../../vitest.config.ts",
32
+ "test:coverage": "vitest run --config ../../vitest.config.ts --coverage",
33
+ "test:update": "vitest run --config ../../vitest.config.ts -u"
34
+ },
28
35
  "files": [
29
36
  "lib/",
30
37
  "!lib/**/*.map",
@@ -34,8 +41,8 @@
34
41
  "README.md"
35
42
  ],
36
43
  "dependencies": {
37
- "@guanghechen/disposable": "^1.0.3",
38
- "@guanghechen/subscriber": "^1.0.3"
44
+ "@guanghechen/disposable": "^2.0.0",
45
+ "@guanghechen/subscriber": "^2.0.0"
39
46
  },
40
- "gitHead": "c46c7cc64c02c61047fbc7dff2ce8f6b21d4da2c"
47
+ "gitHead": "12990a720b31d50d217e2e17a6191256dc94eda6"
41
48
  }