Comments (48)
Working started:
[+] reset
[+] promise
- https://codesandbox.io/s/crimson-tree-n3xog?file=/src/index.js
- https://codesandbox.io/s/fervent-gould-mtkbz?file=/src/index.js
- https://codesandbox.io/s/beautiful-khayyam-w460j
- https://codesandbox.io/s/laughing-waterfall-ou0x3
- https://codesandbox.io/s/stupefied-star-m1pqq?file=/src/index.js
from realar.
Backlog from api-0.6 implementation
[] trigger should be touchable
[] value.touchable(initial) <- The ".from" construction not available for values with "initial" dependency requireds
[] signal.touchable(initial)
[] v.as.readonly()
[] flow.resolve
[] flow as root level exportable factory function
[] .chan
[] value.trigger.from
[] value.trigger.flag.from
[] .map <- sysnonym for .view (on thinking)
[] x.group -- x.op -- x.block
x.block((ctx) => ({ // if returns non undefined
a: ctx.a,
b: ctx.a.select()
})).b.val
[] v.as.signal(), v.as.trigger.flag()
from realar.
Backlog:
[] Add callback to join, and combine. After It possible to use object config for join with callback
[] .as.trigger
[] .as.value.trigger
[] .as.signal.trigger
[] signal.trigger.resolved
[] value.trigger.resolved
[] test case "should work signal.trigger with configured .pre"
[] signal.trigger.from
[] value.trigger.from
[] Add Loader example to documentation
// Second example
const Loader = () => {
const count = value(0);
return {
start: count.updater(v => v + 1),
stop: count.updater(v => v - 1),
pending: count.select(v => v > 0)
}
}
from realar.
Join brainstorm:
[] Add track|untrack for join with callback
I think better way in that case is removing callback support for current version.
because without callback for combine and join no have any conficts for syntax.
I can use track|untrack for join without callback with no disharmony
--> decision for version 0.6:
[] remove callback support for join and combine
[] Add track|untrack for join
...disharmony was stay
--> decision number two) The second
[] rename join to "attach" or "merge"
Task: The saving consistency of track|untrack for append|attach|join|merge function
Have a reason for join without tracking for a set of rective values.
Have a reason join for signals?
value.combine() -> ok
value.join() -> ok
I cant implement signal.combine([], fn and s.join([], fn) because I have not flag for ready all
signals from argument
signal.combine() -> not ok
signal.join() -> not ok
maybe support combine and join only for values now.
For signal I can use merge
const s = signal(0);
s.merge([() => s.val, ...]).val == 0; without callback
Summary:
[] I should implement value.combine([]|{}, fn?), and value(0).combine([] | {}, fn?)
- track|untrack for combine? (I can not support untrack for combine values)
[] No have similar for signal in 0.6 versions.
value.from(() => ({
a: a.val,
b: b.val
}))
value.combine({ a, b }) -> better...
Always tracked, and it used only for values
value(0).combine - have a problem with track|untrack semantic not for 0.6 version.
I should make only value.combine. Aren't It?
Ok. For 0.6 its enough
from realar.
Backlog
[] as.value(dafault_value?)
[] support reactionable for untrack
[] value().get.untrack()
from realar.
Backlog
[] Add default for resolve "Will" type
const v = value(0).filter().default(0)
from realar.
Backlog:
const r = signal();
const u = signal<number>();
const v = value(0);
v.reset.by(r);
v.update.by(u, (state, up_value, up_value_prev) => {
return state + (up_value - (up_value_prev || 0));
});
u(10);
r();
And I think to very interesting idea is the convert "reset" function method to signal
const a = value(0);
a.reset.to(() => console.log("reset"));
from realar.
proposal: local
cosnt v = value(0);
v.flow((value) => {
const ticket = local(() => wait(k));
if (!ticket.val) return flow.stop();
return value;
});
v.flow.filter(() => {
return local(() => wait(k)).val
});
local(expr) // <- bind only first time not necessary bind it every time
// if you need bind every time you should use plain function not local expression.
// synonim of local(expr, []);
local(expr, [<real value dep>, ...])
local(expr, <refresh symbol or expression>);
// or all combination of that
local(expr, <refresh symbol or expression>, [<real value dep>, ...]);
local(expr, [<real value dep>, ...], <refresh symbol or expression>);
from realar.
proposal: wait
const v = value(0);
const s = signal(0);
// wait.all([v, s]) - it is a ready (trigger)
await wait.all([v, s]).promise
await wait.once([v, s]).promise
wait(v) // similar to signal.trigger.from(v) or v.to.signal.trigger()
const k = signal(0);
const m = value(0);
v.flow.wait(m)
.flow.wait.all(k, m) // or synonim to .flow.wait.all([k, m]) -- think about
.flow.wait.race(k, m)
.to((v) => console.log(v));
const k = signal(0);
const m = value(0);
v.flow.wait(m, (v_val, m_val) => return v_val + m_val)
.flow.wait.all([k, m], (v_val, [k_val, m_val]) => return v_val + k_val + m_val) // or stop of course (maybe I can get resolve???)
.flow.wait.race([k, m], (v_val, [k_val, m_val], resolve, v_val_prev) => {});
.to((v) => console.log(v));
from realar.
up: replace useMemo by useRef
You may rely on useMemo as a performance optimization, not as a semantic guarantee. In the future, React may choose to βforgetβ some previously memoized values and recalculate them on next render, e.g. to free memory for offscreen components. Write your code so that it still works without useMemo β and then add it to optimize performance.
from realar.
proposal: chain
Think about "chain" abstraction
const a = value(0);
const b = chain(() => a.val);
assert(b.val === undefined);
a(5);
assert(b.val === undefined);
b.input.to(b.output); // "to" better than "watch"
a(6);
assert(b.val === 6);
from realar.
proposal: pool.flat
private finish_purchase = pool(async () => {
if (this.finish_purchase.count > 1) return; // not count.val here
});
const a = pool(async () => {
if (a.count.val > 1) return a.threads[0].promise; // Return promise from first thread
}
assert(a.flat.pending === false);
assert(chan(async () => {}).flat.pending === false);
from realar.
proposal: signal.union
Collect signals from several values and signals.
Worked as last value of set
const a = value(0);
const b = signal(0);
const u = signal.union(a, b);
u.val === 0;
a(5);
u.val === 5;
b(10);
u.val === 10;
from realar.
proposal: chan
Chan - is therm for define async flow.
Previous proposals for async are "flow.async", pipe.
const a = chan(async (p, k, m) => {}, empty_val?);
a(1,2,3);
const b = a.chan(async (a_val, prev_a_val) => {
});
chan(async () => {})
.flow.filter()
.flow.filter.untrack(() => this.loaded)
.watch.once(() => {});
chan.untrack(async () => {})
.join(b)
.select(([a,b]) => a + b)
.flow.untrack(() => {}, empty_val?)
.watch(() => {})
chan(async () => {}).wrap.filter.not()
// ...
chan.untrack(async () => {}, empty_val)
value.from(() => {})
.chan(async () => {}, empty_val)
.flow.untrack(() => {}, empty_val?)
.flow((a) => a + b.val)
.watch(() => {});
Chan is not a "pool" because "chan" provides only one value, and flows around that value. Overwise "pool" provides a group of parallel or series async execution processes.
But both these meanings can be used with similar async operators.
const t = value(0)
.view(() => {})
.wrap.throttle(300)
.chan.debounce(300);
// .flow.debounce(300); ??
// const t = pool(async () => {}) // "pool" untracked by default for safety reason
// .wrap.throttle // hmmm multiples of parameters and throttle can be strange combination.
// Necessary to think about "throttle" and "debounce" for "pool".
Possible typecast syntax
chan(async () => {}).select.untrack(() => {});
signal(0).to.value() // vs "signal(0).to.value"
value(0).to.signal()
signal(0).to.ready()
signal(0).promise
value(0).promise
value(0).to.ready().promise // promise recreate on demand // vs value(0).to.ready.promise
value.flag()
value.flag.not()
value.ready()
signal.flag() // equivalent to "value.flag"
signal.ready()
// Think about rename "value.ready" to "value.once" or "value.trigger" ...
signal(0).to.trigger() // The primary candidate for changing to
signal(0).to.once() // hmm..
from realar.
low: proposal pool single and pool static chaining factory
pool.single(async () => {
})
// or
pool(async () => {
}).single()
// Will be same result
pool.debounce(300).single().flow(async () => {});
// ok
from realar.
low: proposal flow async and error with unhandled flow unsub
const a = value(0);
const b = value(0);
const c = value(0);
// For a first error on next cases
a.flow.async(async (a) => {
const data = b.flow(() => {}).val; // Error here, necessary for using isolate here
}};
// Flow async proposal
const s = a.flow.async(async (a) => {
if (!a) return stoppable.stop();
return await load_subscriptions();
});
s.val // subscriptions or undefined
s.initialized.val
s.error.val
s.pending()
a.flow.async.debounce(300)
.pipe(
customDebounce,
async (a) => {
if (!a) return stoppable.stop();
const m = c.val; // Subscrible to m or not??
return await load_subscriptions(m);
}
); // readonly async flow
const all_ok = value.combine(a, s.initialized).select(([a, s]) => a && s) // or value.combine([a, s.initialized])
// Rename pool to asyncs)))
// Constructors
value.async(async (v) => {});
signal.async(async (v) => {});
a.flow.async(async (a) => {});
const m = a.flow.async(async (a) => {}).single();
const h = a.sub.async(reactionable, async (state, val) => {}); // h.pending.val
const h_2 = pool(async (a,b,c,d,e) => {
stoppable.stop();
});
// Syntax possibilities
a.async
.debounce(300)
.pipe(
customDebounce,
async (a) => {
if (!a) return stoppable.stop();
const m = c.val; // Subscrible to m or not?? (untrack inside pipe section... hmmmm)
return await load_subscriptions(m);
}
)
.flow(async (a) => {
return await load(a, b.val, c.val); // Depend on change any of that values
})
; // readonly async flow
// Pipe <> Flow same words for not obvious differences... hmm
const s = flow.async(async () => {
return await load(a.val, b.val, c.val);
});
// Syntax possibilities
const t = a.async
.debounce(300)
.flow.untrack(
customDebounce,
async (a) => {
if (!a) return stoppable.stop();
const m = c.val; // not subscribe to c
return await load_subscriptions(m);
}
)
.flow(async (a) => {
return await load(a, b.val, c.val); // subscribe to b and c
})
; // readonly async flow
t.val
t.ready.val
t.error.val
t.pending.val
// flow factory (only track, untrack unsupported)
const s = flow.async(async () => {
return await load(a.val, b.val, c.val);
});
const f_sync = flow(() => {
return sync_load(a.val, b.val, c.val);
});
// And pool
const p = pool(async (a,b,c,d,e) => {
stoppable.stop();
});
p.pending.val
from realar.
low: proposal pool syntax
const a = pool(async () => {});
a.single()
a.debounce(300)
a.throttle()
// or
a.pipe.single()
a.pipe.debounce(300)
a.pipe( ... ) // what is It?
and for values and signals
const a = value(0);
a.pool.debounce(100) // what is it?
from realar.
low: on((stop) => {}, () => {}) implement
from realar.
low: try deprecate stopppable
selector(init_value?, (stop) => {});
selector((stop?) => {});
cycle((stop) => {});
on((stop) => {}, () => {});
// But I think pool no need to use "(stop) =>" syntax, maybe stoppable() is better for pool?
// pool.stop
pool(async () => {
const stop = pool.stop;
pool.stop();
pool.stop.throw();
});
pool.stoppable((stop) => {
return async () => {
}
});
from realar.
low: signal.trigger.from method
Should be added:
signal.trigger.from
signal.trigger.flag.from
from realar.
(Declined) proposal: signal.flag and value.flag
const flag = signal(false).pre((v) => !!v);
from realar.
ver very low: proposal proxy property
const v = value({});
v.proxy.a = 10;
v.update.proxy(p => { // one transaction
p.b = (p.a += 15);
});
from realar.
proposal: name for production ready version "Universal data-flow"
from realar.
low: think about "in one transaction" feature
const s = signal();
const v = value();
on(s, (s_v) => v.val += s_v);
on(() => [s,v], console.log);
on.transaction(s, (s_v) => v.val += s_v); // used one transaction with changed s
// Think about
from realar.
proposal: queue implementation
const q = queue<Type?>(init?: Type[]);
// q(10); // Think about queue - is a reactive value with set of elements or is the signal for add next one... Hmm.
// q.queue // []
q.front // top
q.back // last element
// q.all // array of elements in queue
q.size
q.clear()
//
q.val
q.first: Value
q.last: Value
q.size: Value
q.active: Value
q.clear()
// Support queue for q.wrap and q.view // think about api
// val: <array_of_elements> readonly
// q(<new_element>)
Or q() - no possible, but
q.add(value: Type)
q.val: Type
q.first: Value
q.last: Value
q.size: Value
q.active: Value
q.clear()
// How I can make queue with limited size same as in my swipe impl?
q = queue();
q(values: Type[]);
q.set(values: Type[]);
q.update(...);
q.val: Type;
q.add(value: Type);
q.first: Value
q.last: Value
q.size: Value
q.active: Value
q.empty: Value
q.clear()
//
const t = q.first
t.val: Type
t.started: Value
t.start();
t.release(); // remove item from queue (or dequeue)
// or
t.val: Type
t.start: ready(false).to(true)
t.remove(); // remove item from queue // or ready(false).to(true) too
Decorating add signal
const q = queue<Type>([], (queue, value: Type) => {
const excluded = queue.slice(3);
// const data = queue..
// How to convert value to queue element?
});
const q = queue<Type>();
q.before (Signal)
q.before((value) => {
stoppable.stop();
transaction
check q
remove unnecessary q elems
add new
finish transaction
});
from realar.
proposal: interceptor method
const a = value(5);
const b = value(1);
const unsub = a.interceptor((new_value, current_value, stop?) => {
if (new_value == 1) {
b.set(10);
stop();
return;
}
return current_value + new_value;
});
// stoppable supported
a(1); // b.val === 10, a.val === 5
a(2); // a.val === 7
Think about syntax for sub
interceptions
const v = value(0);
const s = signal(0);
v.sub.intercept(s, (v_value, new_signal_value, stop ) => {
///
});
v.intercept.sub // alias
// or
v.sub.intercept(s, (v_value, new_signal_value, prev_signal_value ) => {
stoppable.stop();
});
v.intercept.sub // alias
from realar.
proposal: pool async oparators
pool.single(async ({ cancelled }) => {
const zip = await search();
if (cancelled()) return;
return await unpack(zip);
});
// If exists active promise each query return It
// pool.throttle(150, async ({ cancelled, abortController?.., cancel }) => {
pool.throttle(150, async ({ stopped, abortController?.., stop }) => {
const zip = await search();
if (zip === 0) stop();
if (stopped()) return;
return await unpack(zip);
});
pool.debounce(150, async function * ({ cancel }) {
const zip = yield search();
if (zip === 0) cancel();
return yield unpack(zip);
});
It is offtopic, but I want to think about throttle and debounce for signals:
const start = signal();
const delayedStart = signal.throttle(150, start);
const a = value();
const delayedA = value.throttle(150, a);
const p = pool(async () => await search());
const delayedP = pool.throttle(150, p);
Maybe only one throttle
function for all necessaries.
from realar.
low: external package realar-form
from realar.
very low: add jsx method
const a = value(0);
return (
<p>{a.jsx}</p>
)
return (
<p>{a.jsx(v => v.map((i, k) => <i key={k}>{i}</i>))}</p>
)
π
a.jsx
a.jsx.if
a.jsx.else
a.jsx.ifelse
a.jsx.map
// or
jsx(a)
jsx.if(a)
jsx.map(a)
// etc..
For making super performant interfaces π
from realar.
very low: state machine impl
This abstraction is necessary for the implementation of serial operations. Reactions on each section of the serial operations.
const m = machine()
.step(a, () => {})
.step(b, () => 0)
.step(machine.oneOf()
.select(a, () => {})
.select(b)
.select(c), () => {})
.loop();
But I think the yield generator function is an interesting way of decision.
loop(function *() {
yield a;
yield b;
yield loop.oneOf([a, b, c]) // or loop.oneOf().select(a, () => {}).select(b, () => {})... chain function
yield loop.race([a, b, c])
yield loop.all([a, b, c])
// Promise namespace operations for suggest
});
from realar.
low: readonly method
const v = value(0);
const readonly_v = v.readonly();
from realar.
Should research about argument passing to "prop" decorator, for the easy binding reactive container to class property:
class A {
@prop(this.store) flat_store
}
from realar.
proposal: value.extract
It should be extract object or array of reactive containers to object or array of usual javascript values.
const email = value('a@x');
const values = value.extract({ email });
console.log(values.email) // [email protected]
Possible kinds of name: "values" consistent with useValues
from realar.
proposal: input as exportable api function
input.handler <- (ev) => ev.target.value
// proposal for another names.
// input.delegate
// input.change
// input.event
input.valid
input.valid.pending
input.validator(
signal<string>().map((state) => /a/.test(state))
)
// input.validator.async() // or
// Interested but no consistency to other code base.
// input.validator((signal) => {
// return signal.as.chan().map(async () => {})
// });
// Final perfect version
input.validator([
signal<string>().filter() <-- what will happens if validator will be stopped
chan<string>().map(async (state) => await fetch_is_valid(state)),
(state) => /aa/.test(state),
async (state) => await ext_test(state)
]);
proposal: remove select.multiple
Improve "select" to "select.multiple" signature
const s = select({ a: (state) => state.a });
The argument can be function, reactive container, object map, or array tuple.
proposal: reactive container as argument of "map" (and array of)
const pipe_double = signal<number>().map(state => state * 2);
value(1).map(pipe_double).val // 2
value(1).map([pipe_double, pipe_double]).val // 4
// Use signature as an array or as reactive container, or usual function signature.
from realar.
low: test ts typings
https://github.com/reduxjs/reselect/blob/master/typescript_test/test.ts#L479
// typings:expect-error
const baz2: string = baz;
from realar.
fix: update component warn from modification in the render function
https://codesandbox.io/s/realar-api-unsubscribe-scopes-control-0sziu?file=/src/App.tsx
Warning: Cannot update a component (`fn`) while rendering a different component (`Form`). To locate the bad setState() call inside `Form`, follow the stack trace as described in https://reactjs.org/link/setstate-in-render
at Form (https://0sziu.csb.app/src/App.tsx:30:35)
at fn (https://0sziu.csb.app/node_modules/realar/build/index.js:697:30)
from realar.
brainstorm: signals two directional synchronization
const a = signal<number>();
const b = signal<number>();
sync(a, b);
sync(b, a);
Signals connection without the infinity loop error
I should realize a way to the bi-directional connection between signals.
const a = signal(0);
const b = signal(0);
sync.bi(a, b);
a.val++
b.val++
assert(a.val === 2)
from realar.
signal.from.select broken ts types with tuples
signal
.from(() => {
return [
buyAnnualLocale.val,
sharedPurchases().annual_subscription.val
]
})
.select(([locale, sub]) => { // both variables have one type "string | Subscription | undefined"
if (!sub) return void 0;
const localized_price = (sub as any)?.localizedPrice;
if (!localized_price) return void 0;
return locale.text
})
from realar.
value(false) broken types for ts <4
const y: Value<boolean> = value(false);
/*
Type 'Value<false, false>' is not assignable to type 'Value<boolean, boolean>'.
Type 'Value<false, false>' is not assignable to type '{ (value: boolean): void; set(value: boolean): void; }'.
Types of parameters 'value' and 'value' are incompatible.
Type 'boolean' is not assignable to type 'false'.ts(2322)
*/
from realar.
proposal: manual rerun cycle outside
const h = cycle(() => {});
h.stop();
h.run();
from realar.
proposal: shortcut not
sharedEye().enabled
.as.signal()
.filter()
.filter(isNext.map(flag => !flag)) // TODO: shortcut not isNext.not()
from realar.
proposal: value with no initial parameter
export const swipeAnimDirection = value<undefined | 'up' | 'down'>();
from realar.
proposal: typings improvement for filter
value<void | number>()
.as.signal()
.filter() // Should remove undefined | null | void from Will signal type
.to(onlyNumberSignal);
from realar.
proposal: new Scope api
const MyLogic = (initial: string) => {}
const MyScope = scope(MyLogic)
const A = () => {
const B = useJsx(() => {
const logic = useScoped(MyLogic)
/* proposal: use scope logic from local section
useLocal(() => {
const logic = scoped(MyLogic) // Warning scope recreation
const logic = scoped.current(MuLogic) // Think about
});
*/
return
});
return <MyScope initial={'hello'}><B>{children}</B></MyScope>
}
from realar.
fix: callback of sync or to methods should be untracked ... hmm.. check it
loader_queue.sync(async queue => {
// should be untracked here
})
from realar.
fix: typings for select without parameter
const toggle = value(false).pre((_, state) => !state);
const enabled = toggle.select(); // Incorrect: ValueReadonly<unknown>
from realar.
proposel: value.will
const t = value.will<number>();
expect(t.val).toBeUndefined();
t.map(n: number => n + 1);
from realar.
proposal
const takeUser = value();
const takeAuth = value();
takeAuth.onChange(takeUser.andUpdate)
takeUser.andSet()
takeUser() - alias for takeUser.andGet
const start = signal();
start.get - doesn't allowed
start.fire(new_value)
takeUser.onChange(start.fire)
start.getValue() - returns value instance
isDirty, isUndefined, isTouched
All methods created only by demand.
start.flow
start.pre
takeUser.compose
from realar.
Related Issues (20)
- low: signal.from.select broken ts types HOT 1
- low: proposal pool syntax HOT 1
- low: proposal flow async and error with unhandled flow unsub HOT 1
- low: proposal pool single and pool static chaining factory HOT 2
- low: proposal join or attach HOT 1
- low: chan proposal HOT 1
- low: proposal signal.union HOT 1
- proposal: sub should be return original object for chaining HOT 1
- proposal: pool.flat HOT 2
- proposal: chain HOT 1
- low: add hook support to scoped instances HOT 1
- low: proposal api for using local, scoped and shared with value return HOT 1
- up: replace useMemo by useRef HOT 1
- proposal: wait HOT 1
- proposal: local HOT 1
- proposal: reset.by and update.by (the "sub" should be removed) HOT 1
- proposal: useValues HOT 1
- proposal: useJsx HOT 1
- Is it okay and if there is a recommended way to use RxJS with realar? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from realar.