UNPKG

redux-easy-async

Version:

Redux Easy Async makes handling asynchronous actions, such as API requests, simple, reliable, and powerful

133 lines (117 loc) 5.94 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); exports.createAsyncAction = undefined; var _assign2 = require('lodash/assign'); var _assign3 = _interopRequireDefault(_assign2); var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var _asyncConstants = require('./async-constants'); var _constants = require('./lib/constants'); var _action = require('./action'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } var decorateActionCreator = function decorateActionCreator(actionCreator, asyncConstants) { var START_TYPE = asyncConstants.START_TYPE, SUCCESS_TYPE = asyncConstants.SUCCESS_TYPE, FAIL_TYPE = asyncConstants.FAIL_TYPE, NAME = asyncConstants.NAME; (0, _assign3.default)(actionCreator, { START_TYPE: START_TYPE, SUCCESS_TYPE: SUCCESS_TYPE, FAIL_TYPE: FAIL_TYPE, NAME: NAME, start: (0, _action.createAction)(START_TYPE), success: (0, _action.createAction)(SUCCESS_TYPE), fail: (0, _action.createAction)(FAIL_TYPE), actionName: NAME }); }; /** * * @kind function * @param {(string|object)} type - can either be a string (e.g. "GET_POSTS") or a * a constants object created with {@link createAsyncConstants}. * @param {Function} fn - action creator function that returns an object with action configuration. * See example below for configuration options. Only `makeRequest is required`. * @param {Object} [options] additional configuration options * @param {Object} [options.namespace=REDUX_EASY_ASYNC_NAMESPACE] the middleware action * type this action will be dispatched with. You most likely don't want to modify this unless for * some reason you want multiple instances of [async middleware]{@link createAsyncMiddleware}. * @return {function} actionCreator * @example <caption>All configuration options for async action</caption> * import { createAsyncAction } from 'redux-easy-async'; * * const myAction = createAsyncAction('MY_ACTION', () => { * return { * // function that makes the actual request. Return value must be a promise. In this example * // `fetch()` returns a promise. **REQUIRED** * makeRequest: () => fetch('/api/posts'), * * // *OPTIONAL* * // additional meta that will be passed to the start, success, and fail actions if any. All * // actions will have the following meta: * // - `actionName` * // - `asyncType`("start", "success", or "fail") * // - `requestStartTime` * // - `asyncID`: an unique id for each request * // Success and fail actions will additionally have: * // - `requestDuration` * // - `resp`: the raw api response. Because of the nature of the promises errors that * // cause the makeRequest promise to be rejected will also get caught here as `resp` * // and cause a failed request action. * meta: {}, * * // function that takes your redux state and returns true or false whether to proceed with * // the request. For example: checking if there is already a similar request in progress or * // the requested data is already cached. *OPTIONAL* * shouldMakeRequest: (state) => true, * * // `parseStart`, `parseSuccess`, and `parseFail` can be useful if you want to modify * // raw API responses, errors, etc. before passing them to your reducer. The return value * // of each becomes the payload for start, success, and fail actions. By default response * // will not be modified. * // * // the return value of `parseStart` becomes the payload for the start action. *OPTIONAL* * parseStart: () => null, * // the return value of `parseSuccess` becomes the payload for the success action. *OPTIONAL* * parseSuccess: resp => resp, * // the return value of `parseFail` becomes the payload for the fail action. *OPTIONAL* * parseFail: resp => resp, * } * * }) */ var createAsyncAction = exports.createAsyncAction = function createAsyncAction(type, fn) { var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; var _options$namespace = options.namespace, namespace = _options$namespace === undefined ? _constants.REDUX_EASY_ASYNC_NAMESPACE : _options$namespace; var asyncConstants = (0, _asyncConstants.getOrCreateAsyncConstants)(type); if (!asyncConstants) { throw new Error('createAsyncAction(type, fn, options): ' + _constants.ERRORS.ASYNC_TYPE_NOT_VALID); } var actionCreator = function actionCreator() { for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } var action = fn.apply(undefined, args); if ((typeof action === 'undefined' ? 'undefined' : _typeof(action)) !== 'object') { throw new Error(_constants.ERRORS.ACTION_NOT_OBJECT); } if (typeof action.makeRequest !== 'function') { throw new Error(_constants.ERRORS.MAKE_REQUEST_NOT_FUNCTION); } return _extends({ type: namespace }, action, { actionCreatorArgs: args, actionName: actionCreator.actionName, startActionCreator: actionCreator.start, successActionCreator: actionCreator.success, failActionCreator: actionCreator.fail }); }; // attach the name and start, success, and fail actions for convenience decorateActionCreator(actionCreator, asyncConstants); return actionCreator; };