Commit b84e42a0 by Vladislav Lagunoff

[update] Добавлен prepareUpdate

parent be3abc83
...@@ -6,6 +6,8 @@ import * as http from '../../http'; ...@@ -6,6 +6,8 @@ import * as http from '../../http';
import { InputHTMLAttributes } from 'react'; import { InputHTMLAttributes } from 'react';
type Err = http.HttpError;
type Props = { type Props = {
}; };
...@@ -15,10 +17,10 @@ type State = { ...@@ -15,10 +17,10 @@ type State = {
response?: http.Response; response?: http.Response;
}; };
const U = Update.bind<State>(); const U = Update.bind<Err, State>();
class Widget extends Update.Component<Props, State> { class Widget extends Update.Component<Err, Props, State> {
state: State = { search: '', pending: false }; state: State = { search: '', pending: false };
handleNameChange: InputHTMLAttributes<HTMLInputElement>['onChange'] = (e) => this.setState({ search: e.target.value }); handleNameChange: InputHTMLAttributes<HTMLInputElement>['onChange'] = (e) => this.setState({ search: e.target.value });
......
...@@ -102,7 +102,7 @@ export function go<Error, State, A>( ...@@ -102,7 +102,7 @@ export function go<Error, State, A>(
if (update instanceof Apply) { if (update instanceof Apply) {
let allInitialized = false; let allInitialized = false;
let subscriptions: Array<Function|undefined|null> = new Array(update.args.length); let cancellers: Array<Canceller|undefined|null> = new Array(update.args.length);
const initializedFlags: Array<true|undefined> = new Array(update.args.length); const initializedFlags: Array<true|undefined> = new Array(update.args.length);
const recentValues: unknown[] = new Array(update.args.length); const recentValues: unknown[] = new Array(update.args.length);
const next = idx => result => { const next = idx => result => {
...@@ -116,46 +116,42 @@ export function go<Error, State, A>( ...@@ -116,46 +116,42 @@ export function go<Error, State, A>(
onNext(update.proj.apply(void 0, recentValues)); onNext(update.proj.apply(void 0, recentValues));
}; };
const complete = idx => () => { const complete = idx => () => {
subscriptions[idx] = null; cancellers[idx] = null;
for (const unsub of subscriptions) if (unsub !== null) return; for (const c of cancellers) if (c !== null) return;
onComplete(); onComplete();
}; };
update.args.forEach((u, idx) => { update.args.forEach((u, idx) => {
const canceller = go(u, getState, setState, next(idx), onError, complete(idx)); const canceller = go(u, getState, setState, next(idx), onError, complete(idx));
if (subscriptions[idx] !== null) subscriptions[idx] = canceller; if (cancellers[idx] !== null) cancellers[idx] = canceller;
}); });
return () => subscriptions.forEach( return () => cancellers.forEach(canceller => canceller ? canceller() : void 0);
funOrNull => funOrNull ? funOrNull() : void 0
);
} }
if (update instanceof Batch) { if (update instanceof Batch) {
if (update.steps.length === 0) { onNext(void 0 as any); onComplete(); return noopFunc; } if (update.steps.length === 0) { onNext(void 0 as any); onComplete(); return noopFunc; }
let subscriptions: Array<Function|null>; let cancellers: Array<Canceller|null>;
const loop = idx => () => { const loop = idx => () => {
subscriptions[idx] = null; cancellers[idx] = null;
for (const unsub of subscriptions) if (unsub !== null) return; for (const unsub of cancellers) if (unsub !== null) return;
onNext(void 0 as any); onNext(void 0 as any);
onComplete(); // If control flow reaches here, that means all nested commands are completed onComplete(); // If control flow reaches here, that means all nested commands are completed
}; };
subscriptions = update.steps.map((u, idx) => go(u, getState, setState, noopFunc, onError, loop(idx))); cancellers = update.steps.map((u, idx) => go(u, getState, setState, noopFunc, onError, loop(idx)));
return () => subscriptions.forEach( return () => cancellers.forEach(canceller => canceller ? canceller() : void 0);
funOrNull => funOrNull ? funOrNull() : void 0
);
} }
if (update instanceof Concat) { if (update instanceof Concat) {
let unsubscribe: Function|null = null; let canceller: Canceller|null = null;
const loop = idx => () => { const loop = idx => () => {
// If condition holds, then all nested effects are completed, therefore we're done // If condition holds, then all nested effects are completed, therefore we're done
if (idx >= update.steps.length) { onNext(void 0 as any); onComplete(); return; } if (idx >= update.steps.length) { onNext(void 0 as any); onComplete(); return; }
unsubscribe = go(update.steps[idx], getState, setState, noopFunc, onError, loop(idx + 1)); canceller = go(update.steps[idx], getState, setState, noopFunc, onError, loop(idx + 1));
}; };
loop(0); loop(0);
return () => unsubscribe ? unsubscribe() : void 0; return () => canceller ? canceller() : void 0;
} }
if (update instanceof Difference) { if (update instanceof Difference) {
...@@ -399,10 +395,11 @@ export class Component<Error, Props, State> extends React.Component<Props, State ...@@ -399,10 +395,11 @@ export class Component<Error, Props, State> extends React.Component<Props, State
setState(updateOrProjOrPatch, callback?) { setState(updateOrProjOrPatch, callback?) {
if (updateOrProjOrPatch instanceof UpdateBase) { if (updateOrProjOrPatch instanceof UpdateBase) {
const onUpdate = this.props['onUpdate'] as unknown; const onUpdate = this.props['onUpdate'] as unknown;
const update = this.prepareUpdate(updateOrProjOrPatch);
if (typeof(onUpdate) === 'function') { if (typeof(onUpdate) === 'function') {
onUpdate(updateOrProjOrPatch); onUpdate(update);
} else { } else {
updateOrProjOrPatch.run(this, callback); update.run(this, callback);
} }
return; return;
} }
...@@ -413,6 +410,10 @@ export class Component<Error, Props, State> extends React.Component<Props, State ...@@ -413,6 +410,10 @@ export class Component<Error, Props, State> extends React.Component<Props, State
return this.setState(new Patch<Error, State, void>(updateOrProjOrPatch, callback)) return this.setState(new Patch<Error, State, void>(updateOrProjOrPatch, callback))
} }
} }
prepareUpdate<A>(update: Update<Error, State, A>): Update<Error, State, A> {
return update;
}
} }
export interface UpdateStatic { export interface UpdateStatic {
...@@ -426,6 +427,7 @@ export interface UpdateStatic { ...@@ -426,6 +427,7 @@ export interface UpdateStatic {
concat: typeof concat, concat: typeof concat,
Component: typeof Component, Component: typeof Component,
bind: typeof bind, bind: typeof bind,
difference: typeof difference,
}; };
...@@ -440,6 +442,7 @@ export const Update = { ...@@ -440,6 +442,7 @@ export const Update = {
concat, concat,
Component, Component,
bind, bind,
difference,
} as UpdateStatic; } as UpdateStatic;
export interface BoundStatics<Error, State> { export interface BoundStatics<Error, State> {
...@@ -460,6 +463,7 @@ export interface BoundStatics<Error, State> { ...@@ -460,6 +463,7 @@ export interface BoundStatics<Error, State> {
modify(proj: (x: State) => State, callback?: () => void): Modify<Error, State, void>; modify(proj: (x: State) => State, callback?: () => void): Modify<Error, State, void>;
effect<Error, Success>(eff: Eff<Error, Success>): Effect<Error, State, Success>; effect<Error, Success>(eff: Eff<Error, Success>): Effect<Error, State, Success>;
get: Get<Error, State, State>; get: Get<Error, State, State>;
difference<A>(update: Update<Error, State, A>, diff: (prev: State, next: State) => State|Update<Error, State, void>): Difference<Error, State, A>;
} }
export function bind<Error, State>() { export function bind<Error, State>() {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment