promise-logic 2.4.4 → 2.4.5
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 +103 -194
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,227 +1,136 @@
|
|
|
1
|
-
# Promise Logic - A Declarative Promise Library Based on Logic Gates
|
|
2
1
|
|
|
3
|
-
This description might sound a bit awkward, but it essentially means a Promise wrapper library designed based on the concept of logic gates, providing a more declarative syntax. However, promiseLogic's implementation is based on promises, so we can say it's a promise-based wrapper library.
|
|
4
2
|
|
|
5
|
-
This design is really interesting. I spent a lot of time thinking about it and realized that promise state machines ultimately have only two outcomes: either fulfilled or rejected. This state design can be abstracted using boolean operations, allowing for declarative writing that reduces our memory burden and mental load during development. Let's look at some examples.
|
|
6
3
|
|
|
7
|
-
|
|
4
|
+
### **1. Core Philosophy**
|
|
8
5
|
|
|
9
|
-
|
|
6
|
+
**Replace API Memory with Logical Concepts**
|
|
7
|
+
The design philosophy of `promise-logic` is: **Developers should focus on business logic, not the details of Promise APIs**.
|
|
8
|
+
Traditional Promise combinations (such as `Promise.all`, `Promise.race`) have naming and semantics that are not intuitive enough, especially in complex asynchronous scenarios where code readability rapidly declines.
|
|
9
|
+
`promise-logic` abstracts asynchronous combinations into logical operations like `AND`, `OR`, `XOR` through the concept of **Logic Gates**, making code semantically clear and self-explanatory.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
npm install promise-logic
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
```javascript
|
|
16
|
-
import PromiseLogic from 'promise-logic';
|
|
17
|
-
|
|
18
|
-
// Native Promise
|
|
19
|
-
const promise = Promise.all([
|
|
20
|
-
Promise.resolve(1),
|
|
21
|
-
Promise.resolve(2),
|
|
22
|
-
Promise.resolve(3)
|
|
23
|
-
]);
|
|
24
|
-
|
|
25
|
-
// Promise Logic -- AND gate
|
|
26
|
-
const promiseLogic = PromiseLogic.and([
|
|
27
|
-
Promise.resolve(1),
|
|
28
|
-
Promise.resolve(2),
|
|
29
|
-
Promise.resolve(3)
|
|
30
|
-
]); // [1,2,3]
|
|
31
|
-
|
|
32
|
-
// This syntax is more semantic, easier to understand, reduces team communication costs, and is more friendly to learners
|
|
33
|
-
|
|
34
|
-
// Native promise
|
|
35
|
-
const promise = Promise.any([
|
|
36
|
-
Promise.resolve(1),
|
|
37
|
-
Promise.reject(2),
|
|
38
|
-
Promise.resolve(3)
|
|
39
|
-
]); // 1
|
|
40
|
-
|
|
41
|
-
// Promise Logic -- OR gate
|
|
42
|
-
const promiseLogicOr = PromiseLogic.or([
|
|
43
|
-
Promise.resolve(1),
|
|
44
|
-
Promise.reject(2),
|
|
45
|
-
Promise.resolve(3)
|
|
46
|
-
]); // 1
|
|
47
|
-
|
|
48
|
-
// The result of or is consistent with native promise.any, but from here, I think you should see the pattern, and there's more to it
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
It also supports TypeScript syntax:
|
|
52
|
-
|
|
53
|
-
```javascript
|
|
54
|
-
const promiseLogic =
|
|
55
|
-
PromiseLogic.and <
|
|
56
|
-
number >
|
|
57
|
-
[Promise.resolve(1), Promise.resolve(2), Promise.resolve(3)]; // [1,2,3]
|
|
58
|
-
|
|
59
|
-
const promiseLogicOr =
|
|
60
|
-
PromiseLogic.or <
|
|
61
|
-
string >
|
|
62
|
-
[
|
|
63
|
-
Promise.resolve('data 1'),
|
|
64
|
-
Promise.reject('error 2'),
|
|
65
|
-
Promise.resolve('data 3')
|
|
66
|
-
]; // 'data 1'
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
#### We can also create flexible combinations for complex request resources
|
|
70
|
-
|
|
71
|
-
```javascript
|
|
72
|
-
// OR + AND
|
|
73
|
-
// Suppose we have a scenario where we want to get data from multiple data sources, need the fastest request result, but also need all requests in one request group to succeed before returning a result. Implementing this with native Promise would be extremely complex
|
|
74
|
-
|
|
75
|
-
// Now we can implement it like this:
|
|
76
|
-
const result = await PromiseLogic.or([
|
|
77
|
-
PromiseLogic.and([
|
|
78
|
-
// Request group 1
|
|
79
|
-
fetch('/api/data1'), // Request 1
|
|
80
|
-
fetch('/api/data2') // Request 2
|
|
81
|
-
]),
|
|
82
|
-
PromiseLogic.and([
|
|
83
|
-
// Request group 2
|
|
84
|
-
fetch('/api/data3'), // Request 3
|
|
85
|
-
fetch('/api/data4') // Request 4
|
|
86
|
-
])
|
|
87
|
-
]); // Result: [fetch('/api/data1'),fetch('/api/data2')] or [fetch('/api/data3'),fetch('/api/data4')] or error
|
|
88
|
-
|
|
89
|
-
// This returns the fastest successful result, and this successful result must come from a request group where all requests in the AND combination have succeeded
|
|
90
|
-
```
|
|
11
|
+
---
|
|
91
12
|
|
|
92
|
-
|
|
13
|
+
### **2. Features**
|
|
93
14
|
|
|
94
|
-
|
|
15
|
+
1. **Logical Semantics**
|
|
16
|
+
- `AND`: All tasks must succeed (equivalent to `Promise.all`)
|
|
17
|
+
- `OR`: At least one task succeeds (equivalent to `Promise.race`)
|
|
18
|
+
- `XOR`: **Exactly one task succeeds** (no direct equivalent in traditional Promise)
|
|
19
|
+
- `NAND`: All tasks fail
|
|
20
|
+
- `Majority`: Most tasks succeed
|
|
95
21
|
|
|
96
|
-
|
|
22
|
+
2. **Zero Dependencies**
|
|
23
|
+
Only depends on native Promise, no additional runtime dependencies.
|
|
97
24
|
|
|
98
|
-
|
|
25
|
+
3. **Full Test Coverage**
|
|
26
|
+
All logic gates have undergone rigorous unit testing to ensure behavior meets expectations.
|
|
99
27
|
|
|
100
|
-
|
|
28
|
+
4. **Clear Error Classification**
|
|
29
|
+
- `PromiseLogicError` unified error type
|
|
30
|
+
- `error.type` distinguishes specific logical errors (e.g., `'XOR_ERROR'`)
|
|
101
31
|
|
|
102
|
-
|
|
32
|
+
---
|
|
103
33
|
|
|
104
|
-
|
|
34
|
+
### **3. Installation**
|
|
105
35
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
- `PromiseLogic.race`
|
|
110
|
-
|
|
111
|
-
### `PromiseLogic.createFlipFlop` - Async Boolean Flip-Flop
|
|
36
|
+
```bash
|
|
37
|
+
npm install promise-logic
|
|
38
|
+
```
|
|
112
39
|
|
|
113
|
-
|
|
40
|
+
---
|
|
114
41
|
|
|
115
|
-
|
|
42
|
+
### **4. Quick Start**
|
|
116
43
|
|
|
44
|
+
#### Example: Primary/Backup Service Call (XOR Scenario)
|
|
117
45
|
```javascript
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
console.log('Disconnecting...');
|
|
136
|
-
await this.connectionState.set(false); // Set disconnected state
|
|
137
|
-
console.log('Disconnected!');
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
async waitForConnection() {
|
|
141
|
-
console.log('Waiting for connection...');
|
|
142
|
-
await this.connectionState.waitFor(true); // Wait until connected
|
|
143
|
-
console.log('Connection established!');
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
async monitorConnection() {
|
|
147
|
-
// Monitor state changes
|
|
148
|
-
while (true) {
|
|
149
|
-
const newState = await this.connectionState.waitForChange();
|
|
150
|
-
console.log('Connection state changed to:', newState ? 'connected' : 'disconnected');
|
|
151
|
-
if (!newState) break; // Exit if disconnected
|
|
46
|
+
import { XOR } from 'promise-logic';
|
|
47
|
+
|
|
48
|
+
// Primary service call
|
|
49
|
+
const primary = fetch('https://api.main.com/data');
|
|
50
|
+
// Backup service call
|
|
51
|
+
const backup = fetch('https://api.backup.com/data');
|
|
52
|
+
|
|
53
|
+
// Execute XOR logic: exactly one success
|
|
54
|
+
XOR(primary, backup)
|
|
55
|
+
.then(result => {
|
|
56
|
+
console.log('Successfully fetched data:', result);
|
|
57
|
+
})
|
|
58
|
+
.catch(error => {
|
|
59
|
+
if (error.type === 'XOR_ERROR') {
|
|
60
|
+
console.error('Both primary and backup services succeeded or failed, which does not meet XOR semantics');
|
|
61
|
+
} else {
|
|
62
|
+
console.error('Network error:', error);
|
|
152
63
|
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
// Usage
|
|
157
|
-
const manager = new ConnectionManager();
|
|
158
|
-
|
|
159
|
-
// Start monitoring in background
|
|
160
|
-
manager.monitorConnection();
|
|
161
|
-
|
|
162
|
-
// Connect and wait
|
|
163
|
-
await manager.connect();
|
|
164
|
-
await manager.waitForConnection();
|
|
64
|
+
});
|
|
65
|
+
```
|
|
165
66
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
67
|
+
#### Example: Majority Decision (Majority Scenario)
|
|
68
|
+
```javascript
|
|
69
|
+
import { Majority } from 'promise-logic';
|
|
70
|
+
|
|
71
|
+
const services = [
|
|
72
|
+
fetch('https://api.node1.com/vote'),
|
|
73
|
+
fetch('https://api.node2.com/vote'),
|
|
74
|
+
fetch('https://api.node3.com/vote')
|
|
75
|
+
];
|
|
76
|
+
|
|
77
|
+
Majority(...services)
|
|
78
|
+
.then(results => {
|
|
79
|
+
console.log('Majority of services returned success:', results);
|
|
80
|
+
})
|
|
81
|
+
.catch(error => {
|
|
82
|
+
console.error('Majority of services failed:', error);
|
|
83
|
+
});
|
|
170
84
|
```
|
|
171
85
|
|
|
172
|
-
|
|
86
|
+
---
|
|
173
87
|
|
|
174
|
-
API
|
|
88
|
+
### **5. API Reference**
|
|
175
89
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
90
|
+
| API | Description |
|
|
91
|
+
| :--------- | :-------------------------------------------------------------------------- |
|
|
92
|
+
| `AND` | All Promises succeed, returns result array; any failure causes overall failure. |
|
|
93
|
+
| `OR` | At least one Promise succeeds, returns first success result; all failures cause overall failure. |
|
|
94
|
+
| `XOR` | **Exactly one Promise succeeds**, returns that result; otherwise throws `XOR_ERROR`. |
|
|
95
|
+
| `NAND` | All Promises fail, returns error array; any success causes overall failure. |
|
|
96
|
+
| `Majority` | More than half of Promises succeed, returns success result array; otherwise overall failure. |
|
|
179
97
|
|
|
180
|
-
|
|
98
|
+
---
|
|
181
99
|
|
|
182
|
-
|
|
100
|
+
### **6. Real-world Application Scenarios**
|
|
183
101
|
|
|
184
|
-
**
|
|
185
|
-
|
|
102
|
+
1. **Primary/Backup Service Calls**
|
|
103
|
+
- Use `XOR` to ensure **exactly one service responds**, avoiding duplicate processing.
|
|
104
|
+
2. **Distributed Decision Making**
|
|
105
|
+
- Use `Majority` to implement majority consensus (e.g., distributed voting).
|
|
106
|
+
3. **Resource Competition**
|
|
107
|
+
- Use `OR` to get the first available resource (e.g., CDN node selection).
|
|
108
|
+
4. **Full-link Validation**
|
|
109
|
+
- Use `AND` to ensure all dependent services succeed (e.g., order creation).
|
|
186
110
|
|
|
187
|
-
|
|
188
|
-
- `set(newState: boolean)`: Sets the new state and returns Promise<boolean>
|
|
189
|
-
- `toggle()`: Toggles the current state and returns Promise<boolean>
|
|
190
|
-
- `waitForChange()`: Returns a Promise that resolves when the state changes
|
|
191
|
-
- `waitFor(targetState: boolean)`: Returns a Promise that resolves when the state matches the target
|
|
111
|
+
---
|
|
192
112
|
|
|
193
|
-
###
|
|
113
|
+
### **7. Contribution Guide**
|
|
194
114
|
|
|
195
|
-
|
|
115
|
+
1. **Development Environment**
|
|
116
|
+
```bash
|
|
117
|
+
git clone https://github.com/haowhite/promise-logic.git
|
|
118
|
+
cd promise-logic
|
|
119
|
+
npm install
|
|
120
|
+
```
|
|
121
|
+
2. **Testing**
|
|
122
|
+
```bash
|
|
123
|
+
npm test
|
|
124
|
+
```
|
|
125
|
+
3. **Commit Guidelines**
|
|
126
|
+
- Commit messages must include prefixes like `feat:` (new feature), `fix:` (bug fix), `docs:` (documentation).
|
|
127
|
+
- Pull Requests must include test cases.
|
|
196
128
|
|
|
197
|
-
|
|
129
|
+
---
|
|
198
130
|
|
|
199
|
-
|
|
200
|
-
- `prefix` (string, optional): String to prepend to all method names
|
|
201
|
-
- `suffix` (string, optional): String to append to all method names
|
|
202
|
-
- `rename` (Record<string, string>, optional): Mapping of original method names to new names
|
|
131
|
+
### **8. Resource Links**
|
|
203
132
|
|
|
204
|
-
**
|
|
205
|
-
|
|
133
|
+
- **GitHub Repository**:[https://github.com/xier123456/promise-logic](https://github.com/xier123456/promise-logic)
|
|
134
|
+
- **npm Package**:[https://www.npmjs.com/package/promise-logic](https://www.npmjs.com/package/promise-logic)
|
|
135
|
+
- **Issue Tracking**:[GitHub Issues](https://github.com/xier123456/promise-logic/issues)
|
|
206
136
|
|
|
207
|
-
```javascript
|
|
208
|
-
// Basic usage - returns all methods with default names
|
|
209
|
-
const logic = createPromiseLogic();
|
|
210
|
-
|
|
211
|
-
// Combined options
|
|
212
|
-
const combined = createPromiseLogic({
|
|
213
|
-
prefix: 'async', // Add prefix
|
|
214
|
-
suffix: 'Op', // Add suffix
|
|
215
|
-
rename: {
|
|
216
|
-
// API renaming
|
|
217
|
-
and: 'Conjunction',
|
|
218
|
-
or: 'Disjunction'
|
|
219
|
-
}
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
// Call combined method (async)+ (Conjunction) + (Op)
|
|
223
|
-
const result = await logic.asycnConjunctionOp([
|
|
224
|
-
fetch('/api/data1'),
|
|
225
|
-
fetch('/api/data2')
|
|
226
|
-
]);
|
|
227
|
-
```
|
package/package.json
CHANGED