UNPKG

@constantiner/fun-ctional

Version:

The library brings most of the familiar functional techniques (like functional composition) to asynchronous world with shining Promises

264 lines (231 loc) 7.88 kB
/** * @constantiner/fun-ctional * The library brings most of the familiar functional techniques (like functional composition) to asynchronous world with shining Promises * * @author Konstantin Kovalev <constantiner@gmail.com> * @version v0.6.6 * @link https://github.com/Constantiner/fun-ctional#readme * @date 30 May 2019 * * MIT License * * Copyright (c) 2018-2019 Konstantin Kovalev * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * */ (function(global, factory) { typeof exports === "object" && typeof module !== "undefined" ? (module.exports = factory()) : typeof define === "function" && define.amd ? define(factory) : ((global = global || self), (global.funCtional = factory())); })(this, function() { "use strict"; function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } } function _asyncToGenerator(fn) { return function() { var self = this, args = arguments; return new Promise(function(resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; } function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); } function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } } function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); } /* eslint-disable unicorn/prefer-spread */ /** * Returns a promise which resolved to array of values from a passed iterable. * An iterable can be a promise to resolve to iterable and then to array. * * @param {Promise|Iterable.<*>} arrayLike Is iterable or promise to resolve to. * @returns {Promise} A promise to resolve to resulting array. */ var extractArrayFromArgument = /*#__PURE__*/ (function() { var _ref = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee(arrayLike) { return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch ((_context.prev = _context.next)) { case 0: _context.t0 = Array; _context.next = 3; return Promise.resolve(arrayLike); case 3: _context.t1 = _context.sent; return _context.abrupt("return", _context.t0.from.call(_context.t0, _context.t1)); case 5: case "end": return _context.stop(); } } }, _callee); }) ); return function extractArrayFromArgument(_x) { return _ref.apply(this, arguments); }; })(); var resolveArrayFromInput = /*#__PURE__*/ (function() { var _ref = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee(iterable) { return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch ((_context.prev = _context.next)) { case 0: _context.t0 = Promise; _context.next = 3; return extractArrayFromArgument(iterable); case 3: _context.t1 = _context.sent; return _context.abrupt("return", _context.t0.all.call(_context.t0, _context.t1)); case 5: case "end": return _context.stop(); } } }, _callee); }) ); return function resolveArrayFromInput(_x) { return _ref.apply(this, arguments); }; })(); var reducer = function reducer(reduceFn) { return function(acc, current, index, array) { return Promise.resolve(acc).then(function(acc) { return reduceFn(acc, current, index, array); }); }; }; var getReducerArguments = function getReducerArguments(args) { var effectiveReduceFn = reducer(args[0]); var effectiveArguments = _toConsumableArray(args); effectiveArguments[0] = effectiveReduceFn; return effectiveArguments; }; /** * Asynchronous composable version of reduce method for iterables ("a" stays for "asynchronous"). * * It gets a list of values (or list of promises, or promise to resolve to list) and performs standard reduce on them. * * Reduce function may be asynchronous to return a promise (to fetch some data etc). * * Initial value of reducer also could be a promise. * * A sample usage is: * * <pre><code>const sum = async (currentSum, invoiceId) => { * const { total:invoiceTotal } = await fetchInvoiceById(invoiceId); * return currentSum + invoiceTotal; * }; * const paymentTotal = await areduce(sum, 0)(fetchInvoiceIds(userId));</code></pre> * * Or the same with acompose: * * <pre><code>const paymentTotal = await acompose(areduce(sum, 0), fetchInvoiceIds)(userId);</code></pre> * * @param {function} callback Function to execute on each element in the array, taking four arguments * (accumulator, currentValue, currentIndex, array). * @param {any} initialValue (optional) Value to use as the first argument to the first call of the callback. * @returns {(iterable : Promise|Iterable.<*>) => Promise} A function which expects an iterable * (or promise resolved to iterable) and returns a Promise. */ var areduce = function() { for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } return ( /*#__PURE__*/ (function() { var _ref = _asyncToGenerator( /*#__PURE__*/ regeneratorRuntime.mark(function _callee(iterable) { return regeneratorRuntime.wrap(function _callee$(_context) { while (1) { switch ((_context.prev = _context.next)) { case 0: _context.t0 = Array.prototype.reduce; _context.next = 3; return resolveArrayFromInput(iterable); case 3: _context.t1 = _context.sent; _context.t2 = getReducerArguments(args); return _context.abrupt( "return", _context.t0.apply.call(_context.t0, _context.t1, _context.t2) ); case 6: case "end": return _context.stop(); } } }, _callee); }) ); return function(_x) { return _ref.apply(this, arguments); }; })() ); }; return areduce; }); //# sourceMappingURL=areduce.js.map