You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
'use strict';
function isPromise(obj) { return !!obj && (typeof obj === 'object' || typeof obj === 'function') && typeof obj.then === 'function'; }
/** * Return a function that will run a function asynchronously or synchronously * * example: * runAsync(wrappedFunction, callback)(...args); * * @param {Function} func Function to run * @param {Function} cb Callback function passed the `func` returned value * @return {Function(arguments)} Arguments to pass to `func`. This function will in turn * return a Promise (Node >= 0.12) or call the callbacks. */
var runAsync = module.exports = function (func, cb) { cb = cb || function () {};
return function () {
var args = arguments;
var promise = new Promise(function (resolve, reject) { var resolved = false; const wrappedResolve = function (value) { if (resolved) { console.warn('Run-async promise already resolved.') } resolved = true; resolve(value); }
var rejected = false; const wrappedReject = function (value) { if (rejected) { console.warn('Run-async promise already rejected.') } rejected = true; reject(value); }
var usingCallback = false; var callbackConflict = false; var contextEnded = false;
var answer = func.apply({ async: function () { if (contextEnded) { console.warn('Run-async async() called outside a valid run-async context, callback will be ignored.'); return function() {}; } if (callbackConflict) { console.warn('Run-async wrapped function (async) returned a promise.\nCalls to async() callback can have unexpected results.'); } usingCallback = true; return function (err, value) { if (err) { wrappedReject(err); } else { wrappedResolve(value); } }; } }, Array.prototype.slice.call(args));
if (usingCallback) { if (isPromise(answer)) { console.warn('Run-async wrapped function (sync) returned a promise but async() callback must be executed to resolve.'); } } else { if (isPromise(answer)) { callbackConflict = true; answer.then(wrappedResolve, wrappedReject); } else { wrappedResolve(answer); } } contextEnded = true; });
promise.then(cb.bind(null, null), cb);
return promise; } };
runAsync.cb = function (func, cb) { return runAsync(function () { var args = Array.prototype.slice.call(arguments); if (args.length === func.length - 1) { args.push(this.async()); } return func.apply(this, args); }, cb); };
|