lib/runs/async.js

const collector = require('./_collector.js');

/**
 * @module pete/lib/runs/async
 */
module.exports = createRunAsync;

/**
 * This runs target async function.
 * Single run is finished after returned Promise is resolved (or fails).
 *
 * @alias module:pete/lib/runs/async
 * @param {Function} fn               to run
 * @param {object}   options
 * @param {any[]}    [options.args]   to pass to target function
 * @param {object}   state            to modify with `current` and `finished` times
 * @return {module:pete/lib/runner~run}
 */
function createRunAsync (fn, options, state) {
	state.runType = module.filename;

	if (!Array.isArray(options.args) || options.args.length < 1) {
		return collector(runAsyncWithoutArgs.bind(null, fn, state), options, state);
	}

	return collector(runAsyncWithArgs.bind(null, fn, state, options.args), options, state);
}

/*
 * TODO: modify collector, so it can provide `ok` and `fail` callbacks instead of `done`.
 *       That will optimize this a bit by removing a need to create arrow function per each call.
 */

/**
 * @private
 * @param {Function} fn      to run
 * @param {object}   state   to modify with `current` time, just before calling target function
 * @param {Function} done    to call after function returns
 */
function runAsyncWithoutArgs (fn, state, done) {
	state.current = process.hrtime.bigint();
	fn()
		.then(() => done())
		.catch(done);
}

/**
 * @private
 * @param {Function} fn      to run
 * @param {object}   state   to modify with `current` time, just before calling target function
 * @param {any[]}    args    to pass to target function
 * @param {Function} done    to call after function returns
 */
function runAsyncWithArgs (fn, state, args, done) {
	state.current = process.hrtime.bigint();
	fn(...args)
		.then(() => done())
		.catch(done);
}