118 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			118 lines
		
	
	
		
			3.7 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 'use strict';
 | |
| 
 | |
| Object.defineProperty(exports, "__esModule", {
 | |
|     value: true
 | |
| });
 | |
| exports.default = asyncify;
 | |
| 
 | |
| var _initialParams = require('./internal/initialParams.js');
 | |
| 
 | |
| var _initialParams2 = _interopRequireDefault(_initialParams);
 | |
| 
 | |
| var _setImmediate = require('./internal/setImmediate.js');
 | |
| 
 | |
| var _setImmediate2 = _interopRequireDefault(_setImmediate);
 | |
| 
 | |
| var _wrapAsync = require('./internal/wrapAsync.js');
 | |
| 
 | |
| function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
 | |
| 
 | |
| /**
 | |
|  * Take a sync function and make it async, passing its return value to a
 | |
|  * callback. This is useful for plugging sync functions into a waterfall,
 | |
|  * series, or other async functions. Any arguments passed to the generated
 | |
|  * function will be passed to the wrapped function (except for the final
 | |
|  * callback argument). Errors thrown will be passed to the callback.
 | |
|  *
 | |
|  * If the function passed to `asyncify` returns a Promise, that promises's
 | |
|  * resolved/rejected state will be used to call the callback, rather than simply
 | |
|  * the synchronous return value.
 | |
|  *
 | |
|  * This also means you can asyncify ES2017 `async` functions.
 | |
|  *
 | |
|  * @name asyncify
 | |
|  * @static
 | |
|  * @memberOf module:Utils
 | |
|  * @method
 | |
|  * @alias wrapSync
 | |
|  * @category Util
 | |
|  * @param {Function} func - The synchronous function, or Promise-returning
 | |
|  * function to convert to an {@link AsyncFunction}.
 | |
|  * @returns {AsyncFunction} An asynchronous wrapper of the `func`. To be
 | |
|  * invoked with `(args..., callback)`.
 | |
|  * @example
 | |
|  *
 | |
|  * // passing a regular synchronous function
 | |
|  * async.waterfall([
 | |
|  *     async.apply(fs.readFile, filename, "utf8"),
 | |
|  *     async.asyncify(JSON.parse),
 | |
|  *     function (data, next) {
 | |
|  *         // data is the result of parsing the text.
 | |
|  *         // If there was a parsing error, it would have been caught.
 | |
|  *     }
 | |
|  * ], callback);
 | |
|  *
 | |
|  * // passing a function returning a promise
 | |
|  * async.waterfall([
 | |
|  *     async.apply(fs.readFile, filename, "utf8"),
 | |
|  *     async.asyncify(function (contents) {
 | |
|  *         return db.model.create(contents);
 | |
|  *     }),
 | |
|  *     function (model, next) {
 | |
|  *         // `model` is the instantiated model object.
 | |
|  *         // If there was an error, this function would be skipped.
 | |
|  *     }
 | |
|  * ], callback);
 | |
|  *
 | |
|  * // es2017 example, though `asyncify` is not needed if your JS environment
 | |
|  * // supports async functions out of the box
 | |
|  * var q = async.queue(async.asyncify(async function(file) {
 | |
|  *     var intermediateStep = await processFile(file);
 | |
|  *     return await somePromise(intermediateStep)
 | |
|  * }));
 | |
|  *
 | |
|  * q.push(files);
 | |
|  */
 | |
| function asyncify(func) {
 | |
|     if ((0, _wrapAsync.isAsync)(func)) {
 | |
|         return function (...args /*, callback*/) {
 | |
|             const callback = args.pop();
 | |
|             const promise = func.apply(this, args);
 | |
|             return handlePromise(promise, callback);
 | |
|         };
 | |
|     }
 | |
| 
 | |
|     return (0, _initialParams2.default)(function (args, callback) {
 | |
|         var result;
 | |
|         try {
 | |
|             result = func.apply(this, args);
 | |
|         } catch (e) {
 | |
|             return callback(e);
 | |
|         }
 | |
|         // if result is Promise object
 | |
|         if (result && typeof result.then === 'function') {
 | |
|             return handlePromise(result, callback);
 | |
|         } else {
 | |
|             callback(null, result);
 | |
|         }
 | |
|     });
 | |
| }
 | |
| 
 | |
| function handlePromise(promise, callback) {
 | |
|     return promise.then(value => {
 | |
|         invokeCallback(callback, null, value);
 | |
|     }, err => {
 | |
|         invokeCallback(callback, err && (err instanceof Error || err.message) ? err : new Error(err));
 | |
|     });
 | |
| }
 | |
| 
 | |
| function invokeCallback(callback, error, value) {
 | |
|     try {
 | |
|         callback(error, value);
 | |
|     } catch (err) {
 | |
|         (0, _setImmediate2.default)(e => {
 | |
|             throw e;
 | |
|         }, err);
 | |
|     }
 | |
| }
 | |
| module.exports = exports.default; |