Skip to content

Instantly share code, notes, and snippets.

View mcavaliere's full-sized avatar

Mike Cavaliere mcavaliere

View GitHub Profile
@mcavaliere
mcavaliere / fetchWithRetries.ts
Created March 13, 2024 19:44
Retry anything function
export interface FetchWithRetriesParams<T> {
fn: () => Promise<T>;
backoffType?: 'exponential' | 'linear';
maxRetries?: number;
retryCount?: number;
delayMs?: number;
// Allows us to define custom logic to determine if the response is successful.
successCondition: (response: T) => boolean;
// Allows us to define custom logic to determine if the response is a failure.
errorCondition?: (response: T) => boolean;
@mcavaliere
mcavaliere / polling-function.jsx
Created August 20, 2020 19:06
ESNext Polling Function
/**
* Run an async function repeatedly until a condition is met, or we hit a max # of attempts.
*
* @param {Number} maxAttempts - Max # of times to run iterate() before we quit.
* @param {Number} frequency - # milliseconds to wait in between attempts.
* @param {Function} iterate - Async. Code to run on every iteration.
* @param {Function} check - Accepts iterate response, return true/false if success criteria are met.
* @param {Function} onSuccess - Success callback.
* @param {Function} onMaxAttemptsExceeded - Failure callback.
*/
@mcavaliere
mcavaliere / helpers.tsx
Created January 15, 2020 13:58
React Context API Logged-in content helpers
export const LoggedInContent: FC<{}> = props => (
<AuthContext.Consumer>
{(auth): React.ReactNode => (auth && auth.token ? props.children : null)}
</AuthContext.Consumer>
);
/**
* Helper to show content only if the user is logged out.
*/
export const LoggedOutContent: FC<{}> = props => (
// Top level. All reusable code goes somewhere under this main object.
var MyApp = {};
// Widgets, and any components that manipulate the DOM.
MyApp.UI = {};
// Classes that have reusable logic or calculation.
MyApp.Lib = {};
// Custom code that works with external javascript libraries in a reusable way.
export default {
configSettingExists( config, key ) {
// Search the config object for the key value
let found = Object.keys( config ).indexOf( key )
return found;
},
indexArrayBy(arr, attrName, group=false) {
// ...
},
// Final config.js
export default class {
init() {
this.config = // ... load the object ...
// For posterity, but we don't need to return it at the moment.
return this.config;
},
settingExists( key ) {
// Old
if ( ! Utils.configSettingExists( config, 'foo' ) ) {
Utils.printConfigFormatInstructions();
}
// New
if ( ! Config.configSettingExists( 'foo' ) ) {
Config.printConfigFormatInstructions();
// Old
import Utils from 'utils.js';
// Load the config.
let config = Utils.initConfig();
// New
import Config from 'config.js';
Config.initConfig();
export default class {
// ...
static printConfigFormatInstructions() {
console.log('Your config file must be in json format, and contain the following keys: foo, bar, baz.');
}
}
export default class {
initConfig() {
this.config = // ... load a json file via AJAX, filesystem, etc. ...
return this.config;
},
configSettingExists( key ) {
// Search the config object for the key value