Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated Voby to 0.2.0 #1011

Merged
merged 10 commits into from
Mar 13, 2022
4 changes: 2 additions & 2 deletions frameworks/keyed/voby/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "js-framework-benchmark-voby",
"version": "0.0.1",
"version": "0.5.0",
"main": "dist/main.js",
"js-framework-benchmark": {
"frameworkVersionFromPackage": "voby"
Expand All @@ -16,7 +16,7 @@
"url": "https://github.com/krausest/js-framework-benchmark.git"
},
"dependencies": {
"voby": "0.1.0"
"voby": "0.5.0"
},
"devDependencies": {
"esbuild": "0.14.23"
Expand Down
54 changes: 27 additions & 27 deletions frameworks/keyed/voby/src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ window.React = {createElement, Fragment};

/* TYPES */

type IDatum = Observable<{ id: string, label: Observable<string>, selected: Observable<boolean>, className: Observable<string> }>;
type IDatum = { id: string, label: Observable<string>, selected: Observable<boolean>, className: Observable<string> };

type IData = IDatum[];

Expand Down Expand Up @@ -39,7 +39,7 @@ const buildData = (() => {
const label = $(`${adjective} ${color} ${noun}`);
const selected = $(false);
const className = $('');
const datum = $( { id, label, selected, className } );
const datum: IDatum = { id, label, selected, className };
data[i] = datum;
};
return data;
Expand All @@ -53,7 +53,7 @@ const Model = (() => {
/* STATE */

let $data = $<IDatum[]>( [] );
let $selected: IDatum | null = null;
let selected: IDatum | null = null;

/* API */

Expand All @@ -71,26 +71,25 @@ const Model = (() => {
};

const add = (): void => {
$data ( [...$data (), ...buildData ( 1000 )] );
$data ( $data ().concat ( buildData ( 1000 ) ) );
};

const update = (): void => {
const data = $data ();
for ( let i = 0, l = data.length; i < l; i += 10 ) {
const $datum = data[i];
const datum = $datum ();
datum.label ( datum.label () + ' !!!' );
const {label} = data[i];
label ( label () + ' !!!' );
}
};

const swapRows = (): void => {
const data = $data ();
if ( data.length <= 998 ) return;
const pos1$ = data[1];
const pos998$ = data[998];
const datum1 = data[1];
const datum998 = data[998];
const data2 = data.slice ();
data2[1] = pos998$;
data2[998] = pos1$;
data2[1] = datum998;
data2[998] = datum1;
$data ( data2 );
};

Expand All @@ -100,25 +99,26 @@ const Model = (() => {

const remove = ( id: string ): void => {
const data = $data ();
const index = data.findIndex ( datum => datum.sample ().id === id );
$data ( [...data.slice ( 0, index ), ...data.slice ( index + 1 )] );
const index = data.findIndex ( datum => datum.id === id );
if ( index === -1 ) return;
$data ( data.slice ( 0, index ).concat ( data.slice ( index + 1 ) ) );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabiospampinato would the shorter .splice() be any slower?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@leeoniya I'm not sure, it might depend on where the deletion happens.

I went with slice/concat because I need to make a new array to have the observable detect it as a change so that it can notify all its subscribers. But now that I think about it it would probably be better to expose the method for notifying subscribers, so that I can just edit the array in place and notify them manually.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure the notification route would have any measurable effect in this specific case, but good to have as option in voby.

for this bench i'd probably leave it written as-is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might shave 1ms or so, but more importantly it would make the code cleaner.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but more importantly it would make the code cleaner.

unless it's mutate & notify in some places, and shallow copy in other places :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unless it's mutate & notify in some places, and shallow copy in other places :)

A little messy, but cleaner than what the code looks like now. For the cleanest code when working with non-trivial data structures I think we ideally want to wrap the data structure in a proxy and extract observables out of it automatically, or something like that. I have another library for that but I haven't wired it with this one, it should be doable 🤔

};

const select = ( id: string ): void => {
if ( $selected ) {
const datum = $selected ();
datum.selected ( false );
datum.className ( '' );
if ( selected ) {
selected.selected ( false );
selected.className ( '' );
selected = null;
}
const data = $data ();
const $datum = data.find ( datum => datum.sample ().id === id )!;
const datum = $datum ();
const datum = data.find ( datum => datum.id === id );
if ( !datum ) return;
datum.selected ( true );
datum.className ( 'danger' );
$selected = $datum;
selected = datum;
};

return { $data, $selected, run, runLots, runWith, add, update, swapRows, clear, remove, select };
return { $data, selected, run, runLots, runWith, add, update, swapRows, clear, remove, select };

})();

Expand All @@ -131,7 +131,7 @@ const Button = ({ id, text, onClick }: { id: string, text: string, onClick: (( e
);

const RowDynamic = ({ id, label, className, onSelect, onRemove }: { id: ObservableMaybe<string>, label: ObservableMaybe<string>, className: ObservableMaybe<string>, onSelect: ObservableMaybe<(( event: MouseEvent ) => any)>, onRemove: ObservableMaybe<(( event: MouseEvent ) => any)> }): JSX.Element => (
<tr class={className}>
<tr className={className}>
<td class="col-md-1">{id}</td>
<td class="col-md-4">
<a onClick={onSelect}>{label}</a>
Expand All @@ -145,7 +145,7 @@ const RowDynamic = ({ id, label, className, onSelect, onRemove }: { id: Observab
</tr>
);

const RowTemplate = template ( RowDynamic );
const RowTemplate = template ( RowDynamic, { recycle: true } );

const App = (): JSX.Element => {

Expand Down Expand Up @@ -173,10 +173,10 @@ const App = (): JSX.Element => {
<table class="table table-hover table-striped test-data">
<tbody>
<For values={$data}>
{( $datum: IDatum ) => {
const {id, label, className} = $datum ();
const onSelect = () => select ( id );
const onRemove = () => remove ( id );
{( datum: IDatum ) => {
const {id, label, className} = datum;
const onSelect = select.bind ( undefined, id );
const onRemove = remove.bind ( undefined, id );
const props = {id, label, className, onSelect, onRemove};
return RowTemplate ( props );
// return RowDynamic ( props );
Expand Down