UNPKG

nope-js-browser

Version:

NoPE Runtime for the Browser. For nodejs please use nope-js-node

184 lines (183 loc) 7.74 kB
/** * @author Martin Karkowski * @email m.karkowski@zema.de */ /** * Delays some execution. Sleeps the amount of time in **ms** * @param delay [ms] * @returns void */ export function sleep(delay) { return new Promise((resolve) => { setTimeout(resolve, delay); }); } /** * Tests if a Function is async or not. * @param func The function to test. * @returns {boolean} The test result. */ export function isAsyncFunction(func) { return func.constructor.name === "AsyncFunction"; } /** * Function which will halt the Process until the Testcallback deliveres "true" * * @export * @param {(() => boolean | Promise<boolean>)} testCallback Function which is used to periodically test the State * @param {{ testFirst?: boolean; maxRetries?: number, timeout?: number, maxTimeout?: number }} [options={}] Options to enhance the behavior. Look at the details * @returns */ export function waitFor(testCallback, options = {}) { const _options = Object.assign({ testFirst: true, delay: 50, }, options); const _isAsync = isAsyncFunction(testCallback); if (_isAsync) { return new Promise(async (resolve, reject) => { if (options.initialWait) { await sleep(options.initialWait); } let _resolve; if (_options.additionalDelay) { _resolve = () => { setTimeout(resolve, _options.additionalDelay); }; } else { _resolve = resolve; } try { if (_options.testFirst && (await testCallback())) { _resolve(); } else { let retryCounter = 0; let timeout = null; let interval = null; // If there is a Timeout, define a Timeout Function, which will // Throw an Error on Timeout. if (_options.maxTimeout) { timeout = setTimeout(async () => { if (interval) { clearInterval(interval); } reject(new Error("Wait has been Timeout")); }, _options.maxTimeout); } // Define a Testfunction, which will periodically test whether the condition is // fullfield or not. Internally it counts the number of retries, if the max allowed // number of retries has been reached => Throw an Error interval = setInterval(async () => { try { if (_options.maxRetries && retryCounter > _options.maxRetries) { // Clear out the Interval clearInterval(interval); // If there is a Timeout clear it as well; if (timeout) { clearTimeout(timeout); } reject(new RangeError("Max Retries has been reached")); } else if (await testCallback()) { // Clear out the Interval clearInterval(interval); // If there is a Timeout clear it as well; if (timeout) { clearTimeout(timeout); } _resolve(); } retryCounter += 1; } catch (err) { reject(err); } }, _options.delay); } } catch (e) { reject(e); } }); } else { return new Promise((resolve, reject) => { const _func = () => { let _resolve; if (_options.additionalDelay) { _resolve = () => { setTimeout(resolve, _options.additionalDelay); }; } else { _resolve = resolve; } try { if (_options.testFirst && testCallback()) { if (_options.additionalDelay) { setTimeout(resolve, _options.additionalDelay); } else { _resolve(); } } else { let retryCounter = 0; let timeout = null; let interval = null; // If there is a Timeout, define a Timeout Function, which will // Throw an Error on Timeout. if (_options.maxTimeout) { timeout = setTimeout(async () => { if (interval) { clearInterval(interval); } reject(new Error("Wait has been Timeout")); }, _options.maxTimeout); } // Define a Testfunction, which will periodically test whether the condition is // fullfield or not. Internally it counts the number of retries, if the max allowed // number of retries has been reached => Throw an Error interval = setInterval(() => { try { if (_options.maxRetries && retryCounter > _options.maxRetries) { // Clear out the Interval clearInterval(interval); // If there is a Timeout clear it as well; if (timeout) { clearTimeout(timeout); } reject(new RangeError("Max Retries has been reached")); } else if (testCallback()) { // Clear out the Interval clearInterval(interval); // If there is a Timeout clear it as well; if (timeout) { clearTimeout(timeout); } _resolve(); } retryCounter += 1; } catch (err) { reject(err); } }, _options.delay); } } catch (e) { reject(e); } }; if (options.initialWait) { setTimeout(_func, options.initialWait); } else { _func(); } }); } }