UNPKG

asyncc

Version:
179 lines (176 loc) 4.76 kB
/** * This is not a `Promise`. * * Chain callback functions with `.then(function (res, cb))` and execute them * as soon as previous callbacks have finished. * * Catch passed or thrown errors with `.catch(function (err, res, cb))` as they may occur. * End the chain with `.end(function (err, res))`. * * If errors are thrown inside a `task` they are catched and can be processed attaching * `.catch()` or `.end()` to the chain. * * This method is similar to {@link module:serial.connect|connect} but allows adding `tasks` on the go through chaining. * * @name NoPromise * @class * @param {Any} arg - initial argument which is passed to first chain * @example <caption>Normal usage</caption> * var arr = [] * var n = new NoPromise(arr) * n.then((res, cb) => { * res.push(1) * cb(null, res) * }).then((res, cb) => { * res.push(2) * cb(null, res) * }).end((err, res) => { * //> err = null * //> res = [1, 2] * //> (arr ==== res) = true * }) * @example <caption>Catch errors</caption> * var arr = [] * var n = new NoPromise(arr) * n.then((res, cb) => { * res.push(1) * cb(null, res) * }).then((res, cb) => { * res.push(2) * cb('err1', res) // <-- cause an error * }).catch((err, res, cb) => { // catches err1 * res.push(err) * cb(null, res) // <-- continue normally * }).then((res, cb) => { * res.push(3) * cb(null, res) * }).catch((err, res, cb) => { // jumps over, as there is no error in the chain * res.push(4) * cb(null, res) * }).then((res, cb) => { * res.push(5) * cb('err2', res) // <-- next error * }).end((err, res) => { * //> err = 'err2' * //> res = [1, 2, 'err1', 3, 5] * //> (arr ==== res) = true * }) * @example <caption>Deferred usage</caption> * var arr = [] * // creates a new instance passing `arr` * var n = new NoPromise(arr) * // execute the first async method * n.then((res, cb) => { * res.push(1) * cb(null, res) * }) * // take a time off * setTimeout(() => { * // continue processing * n.then((res, cb) => { * res.push(2) * cb(null, res) * }).end((err, res) => { * //> err = null * //> res = [1, 2] * //> (arr ==== res) = true * }) * }, 10) */ export default function NoPromise (arg) { this._tasks = [] this.result = arg this.error = undefined this._lock = false } NoPromise.prototype = { /** * runs the next function * @private */ _run: function () { if (this._lock) return this._lock = true let task = this._tasks.shift() const tstType = this.error ? ['catch', 'end'] : ['then', 'end'] while (task && !~tstType.indexOf(task.type)) { task = this._tasks.shift() } if (task) { const cb = (err, res) => { this.error = err this.result = res || this.result this._lock = false this._run() } const fn = task.fn if (task.type === 'end') { // .end fn(this.error, this.result) } else { try { if (task.type === 'catch') { // .catch fn(this.error, this.result, cb) } else { // .then fn(this.result, cb) } } catch (e) { cb(e) } } } else { this._lock = false } }, /** * Chain the next async function * @param {Function} task - async function `function (res: any, cb: Function)`. * Never forget to call `cb(err: <Error>, res: any)` inside `fn` */ then: function (task) { this._tasks.push({ type: 'then', fn: task }) this._run() return this }, /** * Catch any previous errors from the chain * @param {Function} trap - async function `function (err: <Error>, res: any, cb: Function)`. * Never forget to call `cb(err: <Error>, res: any)` inside `fn` */ catch: function (trap) { this._tasks.push({ type: 'catch', fn: trap }) this._run() return this }, /** * End the chain * @param {Function} callback - `function (err: <Error>, res: any)` */ end: function (callback) { this._tasks.push({ type: 'end', fn: callback }) this._run() } } /** * This is not a `Promise`. * * Chain callback functions with `.then(function (res, cb))` and execute them * as soon as previous callbacks have finished. * * Catch passed or thrown errors with `.catch(function (err, res, cb))` as they may occur. * End the chain with `.end(function (err, res))`. * * If errors are thrown inside a `task` they are catched and can be processed attaching * `.catch()` or `.end()` to the chain. * * See full API here {@link NoPromise}. * * @name noPromise * @memberOf module:serial * @static * @method * @param {Any} arg - initial argument which is passed to first chain * @return {NoPromise} */ export function noPromise (arg) { return new NoPromise(arg) }