@fbltd/async 1.0.28 → 1.0.29
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
CHANGED
|
@@ -35,13 +35,13 @@ type IPromiseConfiguration<T> = {
|
|
|
35
35
|
There is no any management of passed data for resolving.
|
|
36
36
|
Returned promise is usual ES promise so it is impossible to fulfill promise twice.
|
|
37
37
|
|
|
38
|
-
###
|
|
38
|
+
### Dependency
|
|
39
39
|
Implementation of reactive model leveraging native JavaScript async features like
|
|
40
40
|
Promises, (async) iterators and generators.
|
|
41
41
|
The version is 0.0.x so keep it in mind
|
|
42
42
|
|
|
43
43
|
```typescript
|
|
44
|
-
const counter = new
|
|
44
|
+
const counter = new Dependency<number>(0);
|
|
45
45
|
|
|
46
46
|
async function onCounterChange() {
|
|
47
47
|
for await (let value of counter) {
|
|
@@ -101,14 +101,14 @@ async function subscribe() {
|
|
|
101
101
|
|
|
102
102
|
#### Framework integrations
|
|
103
103
|
##### React
|
|
104
|
-
Of course, there is a React integration via stream hooks.
|
|
104
|
+
Of course, there is a React integration via stream hooks and HOCs.
|
|
105
105
|
For example, here is classic react counter implementation via useRaceStream hook.
|
|
106
106
|
|
|
107
107
|
```typescript jsx
|
|
108
|
-
type
|
|
108
|
+
type ICounter = {
|
|
109
109
|
dependecy: Dependency,
|
|
110
110
|
}
|
|
111
|
-
export const Counter: React.FC<
|
|
111
|
+
export const Counter: React.FC<ICounter> = React.memo(({
|
|
112
112
|
dependency,
|
|
113
113
|
}) => {
|
|
114
114
|
// num is an instance of DependencyStream
|
|
@@ -121,20 +121,40 @@ export const Counter: React.FC<ITest> = React.memo(({
|
|
|
121
121
|
return (
|
|
122
122
|
<div className={"container"}>
|
|
123
123
|
<button className={"incrementer"}
|
|
124
|
-
// Now result is array of streams values
|
|
125
|
-
// It should be object
|
|
126
124
|
onClick={() => dependency.value++}>
|
|
127
125
|
+
|
|
128
126
|
</button>
|
|
129
127
|
|
|
130
128
|
<div className={cn("display")}>
|
|
131
|
-
{
|
|
132
|
-
// Now result is array of streams values
|
|
133
|
-
// It should be object
|
|
134
|
-
}
|
|
135
129
|
{value.dependency}
|
|
136
130
|
</div>
|
|
137
131
|
</div>
|
|
138
132
|
)
|
|
139
133
|
})
|
|
140
|
-
```
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Or you can use Reaction HOC:
|
|
137
|
+
```typescript jsx
|
|
138
|
+
type ICounter = {
|
|
139
|
+
dependecy: Dependency,
|
|
140
|
+
}
|
|
141
|
+
export const Counter: React.FC<ICounter> = Reactive(({
|
|
142
|
+
dependency,
|
|
143
|
+
}) => {
|
|
144
|
+
|
|
145
|
+
return (
|
|
146
|
+
<div className={"container"}>
|
|
147
|
+
<button className={"incrementer"}
|
|
148
|
+
onClick={() => dependency.value++}>
|
|
149
|
+
+
|
|
150
|
+
</button>
|
|
151
|
+
|
|
152
|
+
<div className={cn("display")}>
|
|
153
|
+
{value.dependency}
|
|
154
|
+
</div>
|
|
155
|
+
</div>
|
|
156
|
+
)
|
|
157
|
+
})
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
######
|
|
@@ -1,52 +1,26 @@
|
|
|
1
1
|
import React, { createElement, useEffect, useState } from "react";
|
|
2
|
-
import { PromiseConfiguration } from "../../../../promise-configuration.js";
|
|
3
2
|
import { observationState } from "../../../observe.state.js";
|
|
4
|
-
|
|
5
|
-
watching: false,
|
|
6
|
-
deps: null
|
|
7
|
-
};
|
|
8
|
-
const watchStack = [];
|
|
9
|
-
function usePromise() {
|
|
10
|
-
const [promise] = useState(() => new PromiseConfiguration());
|
|
11
|
-
return promise;
|
|
12
|
-
}
|
|
3
|
+
import { usePromise } from "./utils.js";
|
|
13
4
|
function Reactive(fn) {
|
|
14
|
-
|
|
15
|
-
// ref.current = dep;
|
|
16
|
-
// const value = dep.value;
|
|
17
|
-
return React.memo(() => {
|
|
5
|
+
return React.memo((props) => {
|
|
18
6
|
const [key, setKey] = useState(Math.random());
|
|
19
7
|
const abortPromise = usePromise();
|
|
20
8
|
useEffect(() => abortPromise.resolve, []);
|
|
21
9
|
observationState.isObserved = true;
|
|
22
|
-
if (currentWatch.watching) {
|
|
23
|
-
watchStack.push(currentWatch);
|
|
24
|
-
currentWatch = {
|
|
25
|
-
watching: true,
|
|
26
|
-
deps: null,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
currentWatch.watching = true;
|
|
31
|
-
}
|
|
32
10
|
useEffect(() => {
|
|
33
11
|
const deps = observationState.getDeps();
|
|
34
12
|
observationState.isObserved = false;
|
|
35
13
|
if (!deps.size)
|
|
36
14
|
return;
|
|
37
|
-
let prom = [
|
|
38
|
-
|
|
39
|
-
];
|
|
40
|
-
deps.forEach((d, i) => {
|
|
41
|
-
prom.push(d.next());
|
|
42
|
-
});
|
|
15
|
+
let prom = [abortPromise.promise];
|
|
16
|
+
deps.forEach(d => prom.push(d.next()));
|
|
43
17
|
Promise.race(prom)
|
|
44
18
|
.then(() => {
|
|
45
19
|
if (abortPromise.isFulfilled)
|
|
46
20
|
return;
|
|
47
21
|
setKey(Math.random());
|
|
48
22
|
});
|
|
49
|
-
}, [key]);
|
|
50
|
-
return createElement(fn);
|
|
23
|
+
}, [key, props]);
|
|
24
|
+
return createElement(fn, props);
|
|
51
25
|
});
|
|
52
26
|
}
|