1import chalk from 'chalk'; 2 3import { env } from './env'; 4import * as Log from '../log'; 5 6/** 7 * Wrap a method and profile the time it takes to execute the method using `EXPO_PROFILE`. 8 * Works best with named functions (i.e. not arrow functions). 9 * 10 * @param fn function to profile. 11 * @param functionName optional name of the function to display in the profile output. 12 */ 13export function profile<IArgs extends any[], T extends (...args: IArgs) => any>( 14 fn: T, 15 functionName: string = fn.name 16): T { 17 if (!env.EXPO_PROFILE) { 18 return fn; 19 } 20 21 const name = chalk.dim(`⏱ [profile] ${functionName ?? 'unknown'}`); 22 23 return ((...args: IArgs) => { 24 // Start the timer. 25 Log.time(name); 26 27 // Invoke the method. 28 const results = fn(...args); 29 30 // If non-promise then return as-is. 31 if (!(results instanceof Promise)) { 32 Log.timeEnd(name); 33 return results; 34 } 35 36 // Otherwise await to profile after the promise resolves. 37 return new Promise<Awaited<ReturnType<T>>>((resolve, reject) => { 38 results.then( 39 (results) => { 40 resolve(results); 41 Log.timeEnd(name); 42 }, 43 (reason) => { 44 reject(reason); 45 Log.timeEnd(name); 46 } 47 ); 48 }); 49 }) as T; 50} 51