UNPKG

@bitblit/ratchet-common

Version:

Common tools for general use

130 lines 5.58 kB
import { Logger } from '../logger/logger.js'; import { ArrayRatchet } from './array-ratchet.js'; import { TimeoutToken } from './timeout-token.js'; import { StopWatch } from './stop-watch.js'; import { LoggerLevelName } from '../logger/logger-level-name.js'; export class PromiseRatchet { static resolveOnEvent(evtSrc, okEvtNames, errEvtNames = [], rval = null) { if (!evtSrc || !okEvtNames || okEvtNames.length === 0 || !evtSrc['on']) { return Promise.reject('Cannot continue - missing source object or name, or the object is not an event source'); } return new Promise((res, rej) => { okEvtNames.forEach((e) => { evtSrc.on(e, () => { res(rval); }); }); if (errEvtNames) { errEvtNames.forEach((e) => { evtSrc.on(e, (err) => { rej(err); }); }); } }); } static timeout(srcPromise, title, timeoutMS) { return Promise.race([srcPromise, PromiseRatchet.createTimeoutPromise(title, timeoutMS)]); } static createTimeoutPromise(title, timeoutMS) { return new Promise((resolve, reject) => { const id = setTimeout(() => { clearTimeout(id); const rval = new TimeoutToken(title, timeoutMS); resolve(rval); }, timeoutMS); }); } static async wait(time) { await PromiseRatchet.createTimeoutPromise('Wait ' + time, time); Logger.silly('Finished wait of %d ms', time); } static dumpResult(result) { Logger.info('Success, result was : \n\n%s\n\n', JSON.stringify(result)); process.exit(0); } static dumpError(err) { Logger.warn('Failure, err was : \n\n%s\n\n -- \n\n%s\n\n', JSON.stringify(err), String(err)); console.trace(); process.exit(1); } static logErrorAndReturnNull(err) { Logger.warn('Failure, err was : \n\n%s\n\n -- \n\n%s\n\n', JSON.stringify(err), String(err)); return null; } static runPromiseAndDump(promise) { promise.then(PromiseRatchet.dumpResult).catch(PromiseRatchet.dumpError); } static async waitFor(testFunction, expectedValue, intervalMS, maxCycles, label = 'waitFor', count = 0) { if (expectedValue == null || intervalMS < 50 || maxCycles < 1 || count < 0 || typeof testFunction != 'function') { Logger.warn('%s: Invalid configuration for waitFor - exiting immediately', label); Logger.warn('ExpectedValue : %s ; interval: %d ; maxCycles: %d ; test : %s', expectedValue, intervalMS, maxCycles, typeof testFunction); return false; } let curVal = null; try { curVal = testFunction(count); } catch (err) { Logger.warn('%s: Caught error while waiting, giving up : %s', label, err); return false; } if (curVal === null) { Logger.debug('%s:CurVal was null - aborting', label); return false; } else if (curVal == expectedValue) { Logger.debug('%s:Found expected value', label); return true; } else if (count > maxCycles) { Logger.debug('%s:Exceeded max cycles, giving up', label); return false; } else { Logger.debug('%s : value not reached yet, waiting (count = %d of %d)', label, count, maxCycles); await PromiseRatchet.wait(intervalMS); return PromiseRatchet.waitFor(testFunction, expectedValue, intervalMS, maxCycles, label, count + 1); } } static async runBoundedParallel(promiseFn, params, context, maxConcurrent = 1, logLevel = LoggerLevelName.debug) { const sw = new StopWatch(); let rval = []; let remain = params; Logger.logByLevel(logLevel, 'Processing %d total elements %d at a time', params.length, maxConcurrent); const ctx = context || this; let processed = 0; const totalCount = remain.length; while (remain.length > 0) { const curBatch = remain.slice(0, Math.min(remain.length, maxConcurrent)); remain = remain.slice(curBatch.length); const proms = curBatch.map((c) => promiseFn.apply(ctx, c)); const output = await Promise.all(proms); processed += proms.length; rval = rval.concat(output); const pct = processed / totalCount; Logger.logByLevel(logLevel, '%d elements remain : %s', remain.length, sw.dumpExpected(pct)); } sw.log(); return rval; } static async runBoundedParallelSingleParam(promiseFn, params, context, maxConcurrent = 1, logLevel = LoggerLevelName.debug) { const wrappedParams = ArrayRatchet.wrapElementsInArray(params); return PromiseRatchet.runBoundedParallel(promiseFn, wrappedParams, context, maxConcurrent, logLevel); } static async asyncForEachSerial(array, callback) { for (let index = 0; index < array.length; index++) { await callback(array[index], index, array); } } static async asyncForEachParallel(array, callback) { const proms = []; for (let index = 0; index < array.length; index++) { proms.push(callback(array[index], index, array)); } await Promise.all(proms); } constructor() { } } //# sourceMappingURL=promise-ratchet.js.map