# Notes-03-28-digital-signing-webpack-dynamic-import-JsonRest-Promise-pattern-performance.measure()

### Digital Signing

#### Terms: <a href="#terms" id="terms"></a>

**digest:** hash of the doc

#### Normal flow: <a href="#normal-flow" id="normal-flow"></a>

**Sender**

```javascript
var digest = hash(doc);
send({ 
    counterpart: doc.copy(), 
    encryption: encrypt(digest)
})
```

**Receiver**

```javascript
var digestByCounterpart = hash(counterpart);
var digest = decrypt(encryption);
isEqual(
    digestByCounterpart,
    digest
);
```

#### With CA: <a href="#with-ca" id="with-ca"></a>

**Sender**

```javascript
var certificate = encryptByCA({
    senderPublicKey,
    senderinfo
}); 

var digest = hash(doc);
send({ 
    counterpart: doc.copy(), 
    encryption: encrypt(digest)
    certificate
})
```

**Receiver**

```javascript
isEqual(
    decryptCA(certificate), 
    { senderPublicKey, senderInfo }
);
isEqual(
    hash(counterpart),
    decrypt(encryption)
);
```

#### Keys <a href="#keys" id="keys"></a>

* CA need to be trusted
* TODO

### Webpack Dynamic Import <a href="#webpack-dynamic-import" id="webpack-dynamic-import"></a>

1. Use `import(${path})`, webpack resolves it in a jsonp way
2. webpack will do code splitting (generate different bundle) for each module that is NOT in the dependency tree of `App.js` (not imported yet)
3. webpack will download the splitted js file when imported is called
4. webpack uses `webpackJsonp()` as a global callback to inject the module into the main bundle (main dependency tree)
5. Once the dynamic import is done, the next same import will be static
6. 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 <a href="#promise-pattern-jsonrest" id="promise-pattern-jsonrest"></a>

```typescript
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
    }));
  }
};
```

```typescript
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);
    };
  }
}
```

```typescript
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 <a href="#promise-pattern" id="promise-pattern"></a>

#### sync Promise <a href="#sync-promise" id="sync-promise"></a>

In runkit:

```javascript
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 <a href="#chaining" id="chaining"></a>

[Reference Link](https://javascript.info/promise-chaining)

```javascript
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 <a href="#measure-regexp" id="measure-regexp"></a>

```javascript
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 <a href="#regex-check" id="regex-check"></a>

**with create regex everytime**

```javascript
measurePerformance('1', () => /^[0-9]{5,10}$/.test('1111'));
// 1 milliseconds: 0.11999998241662979
// 1 milliseconds: 0.12999994214624166
// 1 milliseconds: 0.16499997582286596
```

**with cached regex object**

```javascript
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**

```javascript
measurePerformance('1', () => isNaN('11111') && '11111'.length > 5 && '11111'.length < 10);
// 1 milliseconds: 0.030000112019479275
// 1 milliseconds: 0.059999991208314896
// 1 milliseconds: 0.024999957531690598
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://notes.lirenxn.com/2020/notes-03-28-digital-signing-webpack-dynamic-import-jsonrest-promise-pattern-performance.measure.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
