Skip to content

Commit

Permalink
Convert to typescript
Browse files Browse the repository at this point in the history
  • Loading branch information
graup committed Mar 23, 2020
1 parent 29d5332 commit be3e25c
Show file tree
Hide file tree
Showing 10 changed files with 808 additions and 76 deletions.
3 changes: 2 additions & 1 deletion .babelrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"presets": [
["@babel/env", { "targets": { "node": "current" } }]
["@babel/env", { "targets": { "node": "current" } }],
"@babel/preset-typescript"
],
}
10 changes: 8 additions & 2 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@ module.exports = {
"node": true,
"mocha": true,
},
"extends": "eslint:recommended",
"parser": "@typescript-eslint/parser",
"plugins": ["@typescript-eslint"],
"extends": [
"plugin:@typescript-eslint/recommended",
"eslint:recommended",
],
"parserOptions": {
"ecmaVersion": 2018,
"sourceType": "module"
Expand Down Expand Up @@ -37,6 +42,7 @@ module.exports = {
"prefer-arrow-callback": "warn",
"prefer-const": "warn",
"no-var": "error",
"no-unused-vars": "warn"
"no-unused-vars": "warn",
"@typescript-eslint/no-explicit-any": "off"
}
};
50 changes: 50 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
interface Options {
slow: () => void;
slowTime: number;
fast: () => void;
fastTime: number;
}
declare type Main<T> = Promise<T> | ((...args: any[]) => Promise<T>);
/**
* Wait a minimum amount of time, even when an operation (such as an API response) finished very quickly.
* Also good for testing, as production load times are usually slower than
* in a development environment.
*
* Example:
* const waitMinimum = loadAndWait();
* (... do something that the user expects to take some time, e.g. loading data ...)
* await waitMinimum();
*
* @param {number} minimumLoadTime duration in ms, default 500
* @return {loadAndWait~waitMinimum}
*/
declare function loadAndWait(minimumLoadTime?: number): ((callbackIfFast: () => void) => Promise<void>);
/**
* Register a function to be called when an operation is considered slow.
*
* Example:
* const loadingFinished = waitOrLoad(() => {
* console.log('loading is slow');
* });
* (... do something that the user expects to take some time, e.g. loading data ...)
* loadingFinished();
*
* @param {function} callbackIfSlow function to call when operation is taking longer than maximumLoadTime.
* @param {number} maximumLoadTime duration in ms, default 1500
* @return {waitOrLoad~loadingFinished}
*/
declare function waitOrLoad(callbackIfSlow: () => void, maximumLoadTime?: number): () => void;
/**
* Decorator to add "slow" and "fast" timing hooks to any async operation.
* This returns the return value of the main function and also lets exceptions go through.
*
* @param {function|Promise} main execution function to be timed, or promise to be awaited
* @param {object} options
* @param {function} options.slow function to be called when operation is slow
* @param {number?} options.slowTime time after which the operation is considered slow. Default: 1500
* @param {function} options.fast function to be called when operation is fast
* @param {number?} options.fastTime time until which the operation is considered fast. Default: 500
* @return {any} return value of main function
*/
declare function timedAsync<T>(main: Main<T>, options: Options): Promise<T>;
export { loadAndWait, waitOrLoad, timedAsync };
4 changes: 2 additions & 2 deletions index.es5.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ function loadAndWait(minimumLoadTime = FAST_LOAD_TIME) {

return function waitMinimum(callbackIfFast) {
return new Promise(resolve => {
const loadDuration = new Date() - startedLoading;
const loadDuration = +new Date() - startedLoading;
const waitTime = clamp(minimumLoadTime - loadDuration, 0, minimumLoadTime);

if (waitTime > 0 && typeof callbackIfFast === 'function') {
Expand Down Expand Up @@ -87,7 +87,7 @@ function waitOrLoad(callbackIfSlow, maximumLoadTime = SLOW_LOAD_TIME) {
*/


async function timedAsync(main, options = {}) {
async function timedAsync(main, options) {
const waitMinimum = loadAndWait(options.fastTime || FAST_LOAD_TIME);
let loadingFinished;

Expand Down
40 changes: 16 additions & 24 deletions index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions index.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

104 changes: 104 additions & 0 deletions index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@

interface Options {
slow: () => void;
slowTime: number;
fast: () => void;
fastTime: number;
}
type Main<T> = Promise<T> | ((...args: any[]) => Promise<T>);

const FAST_LOAD_TIME = 500; // miliseconds
const SLOW_LOAD_TIME = 1500; // miliseconds

const clamp = (num: number, min: number, max: number): number => Math.min(Math.max(num, min), max);

/**
* Wait a minimum amount of time, even when an operation (such as an API response) finished very quickly.
* Also good for testing, as production load times are usually slower than
* in a development environment.
*
* Example:
* const waitMinimum = loadAndWait();
* (... do something that the user expects to take some time, e.g. loading data ...)
* await waitMinimum();
*
* @param {number} minimumLoadTime duration in ms, default 500
* @return {loadAndWait~waitMinimum}
*/
function loadAndWait(minimumLoadTime: number = FAST_LOAD_TIME): ((callbackIfFast: () => void) => Promise<void>) {
const startedLoading = + new Date();
/**
* @param {function} callbackIfFast function to call if operation finished in less than minimumLoadTime.
* @return {Promise} promise that resolves when minimumLoadTime minus wait time has passed (possibly immediately).
*/
return function waitMinimum(callbackIfFast): Promise<void> {
return new Promise(resolve => {
const loadDuration = + new Date() - startedLoading;
const waitTime = clamp(minimumLoadTime-loadDuration, 0, minimumLoadTime);
if (waitTime > 0 && typeof callbackIfFast === 'function') {
callbackIfFast();
}
setTimeout(resolve, waitTime);
});
};
}

/**
* Register a function to be called when an operation is considered slow.
*
* Example:
* const loadingFinished = waitOrLoad(() => {
* console.log('loading is slow');
* });
* (... do something that the user expects to take some time, e.g. loading data ...)
* loadingFinished();
*
* @param {function} callbackIfSlow function to call when operation is taking longer than maximumLoadTime.
* @param {number} maximumLoadTime duration in ms, default 1500
* @return {waitOrLoad~loadingFinished}
*/
function waitOrLoad(callbackIfSlow: () => void, maximumLoadTime: number = SLOW_LOAD_TIME): () => void {
const timeout = setTimeout(callbackIfSlow, maximumLoadTime);
/**
* Call this function after the operation has finished.
* This cancels the timeout so that the previously registered, not yet executed callback is not called.
*/
return function loadingFinished(): void {
clearTimeout(timeout);
};
}

/**
* Decorator to add "slow" and "fast" timing hooks to any async operation.
* This returns the return value of the main function and also lets exceptions go through.
*
* @param {function|Promise} main execution function to be timed, or promise to be awaited
* @param {object} options
* @param {function} options.slow function to be called when operation is slow
* @param {number?} options.slowTime time after which the operation is considered slow. Default: 1500
* @param {function} options.fast function to be called when operation is fast
* @param {number?} options.fastTime time until which the operation is considered fast. Default: 500
* @return {any} return value of main function
*/
async function timedAsync<T>(main: Main<T>, options: Options): Promise<T> {
const waitMinimum = loadAndWait(options.fastTime || FAST_LOAD_TIME);
let loadingFinished;
if (typeof options.slow === 'function') {
loadingFinished = waitOrLoad(options.slow, options.slowTime || SLOW_LOAD_TIME);
}
try {
const promise = typeof main === 'function' ? main() : main;
return await promise;
} finally {
if (typeof loadingFinished !== 'undefined') {
loadingFinished();
}
await waitMinimum(options.fast);
}
}

export {
loadAndWait,
waitOrLoad,
timedAsync
};
Loading

0 comments on commit be3e25c

Please sign in to comment.