Notes-03-28-digital-signing-webpack-dynamic-import-JsonRest-Promise-pattern-performance.measure()
Digital Signing
Terms:
digest: hash of the doc
Normal flow:
Sender
var digest = hash(doc);
send({
counterpart: doc.copy(),
encryption: encrypt(digest)
})
Receiver
var digestByCounterpart = hash(counterpart);
var digest = decrypt(encryption);
isEqual(
digestByCounterpart,
digest
);
With CA:
Sender
var certificate = encryptByCA({
senderPublicKey,
senderinfo
});
var digest = hash(doc);
send({
counterpart: doc.copy(),
encryption: encrypt(digest)
certificate
})
Receiver
isEqual(
decryptCA(certificate),
{ senderPublicKey, senderInfo }
);
isEqual(
hash(counterpart),
decrypt(encryption)
);
Keys
CA need to be trusted
TODO
Webpack Dynamic Import
Use
import(${path})
, webpack resolves it in a jsonp waywebpack will do code splitting (generate different bundle) for each module that is NOT in the dependency tree of
App.js
(not imported yet)webpack will download the splitted js file when imported is called
webpack uses
webpackJsonp()
as a global callback to inject the module into the main bundle (main dependency tree)Once the dynamic import is done, the next same import will be static
if the dynamic imported file is already in main dependency tree(be imported my some other file), it will not be code splitted, dynamic import will be transformed to static as 5 does
Promise pattern JSONRest
private subscriberPublicGroupStores: { [subscriberId: string]: JsonRest } = {};
private getSubscriberPublicGroupStore = (subscriberId: string) => {
const subscriberPublicGroupStores = this.subscriberPublicGroupStores;
if (subscriberId in subscriberPublicGroupStores) {
return subscriberPublicGroupStores[subscriberId];
} else {
const encodedSubscriberId = encodeURIComponent(subscriberId);
return (subscriberPublicGroupStores[subscriberId] = new JsonRest<Array<LookupItemModel>>({
url: `/Workspaces/public-groups/subscribers/${encodedSubscriberId}`,
immediate: true
}));
}
};
class JsonRest<R = any> {
private url: string;
private immediate: boolean = true;
private data?: Promise<R>;
private subscribers: { resolve: Array<Function>; reject: Array<Function> } = { resolve: [], reject: [] };
constructor(config: string | Config<R>) {
if (typeof config === 'string') {
this.url = config;
} else {
this.url = config.url;
this.immediate = config.immediate;
}
if (this.immediate) {
this.query();
}
}
public query = (): Promise<R> => {
if (!this.data) {
this.data = http.get<R>(this.url);
}
return this.data!.then(data => {
this.subscribers.resolve.forEach(fn => fn(data));
return data;
}) //
.catch(err => {
this.subscribers.reject.forEach(fn => fn(err));
throw err;
});
};
public subscribe(event: SubscriptionType, callback: Function) {
this.subscribers[event].push(callback);
return () => {
this.subscribers[event] = this.subscribers[event].filter(fn => fn !== callback);
};
}
}
class SelectField extends BaseField<{}> {
private _unsubscribe?: Function;
componentWillReceiveProps(props: any) {
// remove previouse subscription
if ((this.props as any).store !== props.store && this._unsubscribe) {
this._unsubscribe();
this._unsubscribe = undefined;
}
}
componentWillUnmount() {
this._unsubscribe && this._unsubscribe();
}
render() {
const props = this.resolveComponentProps();
if (props.preSelectFirst && props.store) {
if (!this._unsubscribe) {
this._unsubscribe = props.store.subscribe('resolve', (items: Array<any>) => {
const {
form: { setFieldValue },
field: { value }
} = this.props;
// Check the previous value
// If there is no value, pre-select if the dropdown only has one option
// Otherwise check if the drop down contains current selected option
// TODO: Posibily improve logic
if (!value) {
if (items.length === 1) {
setFieldValue(props.name, items[0].id);
}
} else if (items.findIndex(item => item.id === value) === -1) {
setFieldValue(props.name, '');
}
});
}
}
return <Select {...props} />;
}
}
Promise Pattern
sync Promise
In runkit:
var { SynchronousPromise } = require("synchronous-promise");
console.log('init');
var as = new Promise((resolve, reject) => { resolve('happy as!'); });
as.then(message => { console.log(message); });
console.log('block1');
var initial = new SynchronousPromise((resolve, reject) => { resolve('happy!'); });
initial.then(message => { console.log(message); });
console.log('end');
will print out:
init
block1
happy! // sync
end
happy as! // async
chaining
function logFail(v) {
console.log('fail' + v);
}
function logSuccess(v) {
console.log('success' + v);
}
var a = new Promise( resolve => {
resolve(1);
}).then(r => {
logSuccess(r);
return r + 1;
}).catch(e => {
logFail(e);
throw e;
}).then(r => {
logSuccess(r);
throw r + 1;
}).catch(e => {
logFail(e);
throw e;
}).then(r => {
logSuccess(r);
throw r + 1;
}).catch(e => {
logFail(e);
return e + 1;
}).then(
r => {
logSuccess(r);
throw r + 1;
},
e => {
logFail(e);
throw e;
}
).catch(e => {
logFail(e + ' catch and error in then is different');
});
will output
success1
success2
fail3
fail3
success4
fail5 catch and error in then is different
Measure Regexp
function measurePerformance(name, callback) {
performance.mark(`${name}-start`);
const res = callback();
performance.mark(`${name}-end`);
performance.measure(name, `${name}-start`, `${name}-end`);
const entries = performance.getEntriesByName(name);
const latestMeasure = performance.getEntriesByName(name)[entries.length - 1];
console.debug(`${name} milliseconds:`, latestMeasure.duration);
console.debug(latestMeasure);
return res;
}
Regex check
with create regex everytime
measurePerformance('1', () => /^[0-9]{5,10}$/.test('1111'));
// 1 milliseconds: 0.11999998241662979
// 1 milliseconds: 0.12999994214624166
// 1 milliseconds: 0.16499997582286596
with cached regex object
const cachedReg = /^[0-9]{5,10}$/;
measurePerformance('1', () => cachedReg.test('1111'));
// 1 milliseconds: 0.024999957531690598
// 1 milliseconds: 0.029999995604157448
// Change test value
measurePerformance('1', () => cachedReg.test('11112'));
// 1 milliseconds: 0.024999957531690598
for manual check
measurePerformance('1', () => isNaN('11111') && '11111'.length > 5 && '11111'.length < 10);
// 1 milliseconds: 0.030000112019479275
// 1 milliseconds: 0.059999991208314896
// 1 milliseconds: 0.024999957531690598
Last updated
Was this helpful?