`

react-resource源码

 
阅读更多

react-resource.js发送请求,返回promise,不像jquery那样可以自由设置contentType,数据预处理等

 

/* ==========================================================================
   [COMPONENT] React-Resource
   --------------------------------------------------------------------------
   Component for creating http restful requests by using Promises.
   Written to symbiose with RefluxJs async actions.
   ========================================================================== */

'use strict';

Object.defineProperty(exports, '__esModule', {
    value: true
});

// _createClass(Constructor,protoProps,staticProps) 创建构造函数,定义静态方法、原型属性和方法
// protoProps用以定义Constructor.prototype 各属性、方法的访问器属性
// staticProps用以定义Constructor 各属性、方法的访问器属性,[{key,enumerable,configurable,value}]形式
var _createClass = (function () {// 利用自执行匿名函数优化defineProperties书写
    function defineProperties(target, props) { 
        for (var i = 0; i < props.length; i++) { 
            var descriptor = props[i]; 
            descriptor.enumerable = descriptor.enumerable || false; 
            descriptor.configurable = true; 
            if ('value' in descriptor) descriptor.writable = true; 
            Object.defineProperty(target, descriptor.key, descriptor); 
        } 
    } 
    return function (Constructor, protoProps, staticProps) { 
        if (protoProps) defineProperties(Constructor.prototype, protoProps); 
        if (staticProps) defineProperties(Constructor, staticProps); 
        return Constructor; 
    }; 
})();

exports['default'] = ReactResource;

function _interopRequireDefault(obj) { 
    return obj && obj.__esModule ? obj : { 'default': obj }; 
}

// 构造函数只能通过new关键字调用
function _classCallCheck(instance, Constructor) { 
    if (!(instance instanceof Constructor)) { 
        throw new TypeError('Cannot call a class as a function'); 
    }
}

var _promise = require('promise');
var _promise2 = _interopRequireDefault(_promise);

var _superagent = require('superagent');
var _superagent2 = _interopRequireDefault(_superagent);

// lodash工具函数集,类似underscore
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);

// ------------------------------------------------------------------------------
// Resource class creator
// url用于给actionsConfig中未设置url的action赋值
// mapping为{key:string};后续url中用"{"、"}"括起的string,将被替换成actionname方法解析参数获得的source.key
// actionsConfig为{actionname:{url,params,method,isArray}}形式,actionname为添加给Resource的静态方法名
// 使用:
//      ReactResource(url, mappings, actionsConfig)[actionname]([source],[queryParams],[bodyData],[resolveFn],[rejectFn])
//      或者 new ReactResource(url, mappings, actionsConfig)()["$"+actionname]([source],[queryParams],[bodyData],[resolveFn],[rejectFn])
function ReactResource(url, mappings, actionsConfig) {
    // 实例含url、mapping、actionsConfig属性,this.actionsConfig是默认actions和用户配置actions复合后的结果
    var resourceConfig = new ResourceConfig(url, mappings, actionsConfig);

    function Resource(initObject) {
        // HelpersAndParsers.copyPureAttributes拷贝对象输出,"$"起始的键不拷贝
        HelpersAndParsers.copyPureAttributes(initObject, this);
        ActionsBuilder.createInstanceActions(resourceConfig, this);
    }
    ActionsBuilder.createClassActions(resourceConfig, Resource);

    return Resource;
}

// 拦截器{response:function(res){},rejection:function(err,res)},引用对象形式处理响应
ReactResource.interceptors = [];
ReactResource.add_interceptor = function (interceptorObj) {
    if (typeof interceptorObj == 'object' && (typeof interceptorObj.response == 'function' || typeof interceptorObj.rejection == 'function')) {
        ReactResource.interceptors.push(interceptorObj);
    }
};

var ActionsBuilder = (function () {
    function ActionsBuilder() {
        _classCallCheck(this, ActionsBuilder);
    }

    // 添加静态方法
    // ActionsBuilder.createClassActions创建resourceClass.query|get|update|delete|create|[customMethodName]方法,用于发送请求,返回promise
    //     其中,customMethodName来自用户传入ReactResource的actionsConfig参数{customMethodName:{url,query,method,isArray}}
    //     resourceClass是ReactResource构造函数中的Resource构造函数,即用户调用ReactResource(url,mapping,actionsConfig)返回值
    _createClass(ActionsBuilder, null, [{
        key: 'createClassActions',
        value: function createClassActions(resourceConfig, resourceClass) {
            _lodash2['default'].forEach(Object.keys(resourceConfig.actionsConfig), function (actionName) {
                resourceClass[actionName] = ActionsBuilder.buildActionFromConfig(actionName, resourceConfig, {});
            });
        }
    }, {
        key: 'createInstanceActions',
        // resourceClass实例添加方法$query|$get|$update|$delete|$create|["$"+customMethodName][actionName],用于发送请求,返回promise
        value: function createInstanceActions(resourceConfig, resourceInstance) {
            _lodash2['default'].forEach(Object.keys(resourceConfig.actionsConfig), function (actionName) {
                resourceInstance["$" + actionName] = ActionsBuilder.buildActionFromConfig(actionName, resourceConfig, resourceInstance);
            });
        }
    }, {
        key: 'buildActionFromConfig',

        // 构建resourceClass[actionName]函数内容体
        value: function buildActionFromConfig(actionName, resourceConfig) {
            var ModelInstance = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

            // 构建resourceClass[actionName]函数内容体
            return function () {
                // 接收resourceClass[actionName]方法传参
                for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
                    args[_key] = arguments[_key];
                }

                // HelpersAndParsers.parseArgs获取本次请求的promiseConfig,形为{url,source,queryParams,bodyData,resolveFn,rejectFn}
                // 请求由resourceClass[actionName]发起
                // resourceClass[actionName]即ReactResource(url,mapping,actionsConfig)[actionName]
                // 或new ReactResource(url,mapping,actionsConfig)["$"+actionName]
                var promiseConfig = HelpersAndParsers.parseArgs.apply(HelpersAndParsers, [actionName, resourceConfig, ModelInstance].concat(args));
                

                return ActionsBuilder.buildPromiseFromAction(actionName, resourceConfig, promiseConfig);
            };
        }
    }, {
        key: 'buildPromiseFromAction',

        // 发送请求,返回promise
        value: function buildPromiseFromAction(actionName, resourceConfig, promiseConfig) {
            var actionConfig = resourceConfig.actionsConfig[actionName];
            return new _promise2['default'](function (resolvePromiseFn, rejectPromiseFn) {
                var newRequest = _superagent2['default'],
                    actionMethod = actionConfig.method.toUpperCase();
                switch (actionMethod) {
                    case 'GET':
                        newRequest = newRequest.get(promiseConfig.url);
                        break;
                    case 'POST':
                        newRequest = newRequest.post(promiseConfig.url);
                        break;
                    case 'PUT':
                    case 'PATCH':
                        newRequest = newRequest.put(promiseConfig.url);
                        break;
                    case 'DELETE':
                        newRequest = newRequest.del(promiseConfig.url);
                        break;
                }

                // JSON
                newRequest.set('Accept', 'application/json');

                // 添加url携带参数,get、post请求都有
                newRequest.query(_lodash2['default'].merge(_lodash2['default'].cloneDeep(actionConfig.params), promiseConfig.queryParams));

                // 添加json格式数据,post请求独有
                if (!_lodash2['default'].isEmpty(promiseConfig.bodyData) && ACTIONS_WITH_BODY.indexOf(actionMethod) > -1) {
                    newRequest.send(promiseConfig.bodyData);
                }

                newRequest.end(function (err, res) {
                    if (err === null) {
                        _lodash2['default'].forEach(ReactResource.interceptors, function (interceptor) {
                            if (typeof interceptor.response == 'function') interceptor.response(res);
                        });

                        resolvePromiseFn(res && res.body);
                        if (promiseConfig.resolveFn && typeof promiseConfig.resolveFn == 'function') {
                            promiseConfig.resolveFn(res && res.body);
                        }
                    } else {
                        _lodash2['default'].forEach(ReactResource.interceptors, function (interceptor) {
                            if (typeof interceptor.rejection == 'function') interceptor.rejection(err, res);
                        });

                        rejectPromiseFn(res && res.body || err);
                        if (promiseConfig.rejectFn && typeof promiseConfig.rejectFn == 'function') {
                            promiseConfig.rejectFn(res && res.body || err);
                        }
                    }
                  });
            });
        }
    }]);

    return ActionsBuilder;
})();

// 实例含url、mapping、actionsConfig属性,this.actionsConfig是默认actions和用户配置actions复合后的结果
var ResourceConfig = (function () {// 利用自调用匿名函数,构造函数的静态方法和原型方法赋值
    function ResourceConfig(url) {
        var mappings = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];
        var extraActionsConfig = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

        _classCallCheck(this, ResourceConfig);

        if (!url) throw Error("Cant create resource config without url");
        this.url = url;
        this.mappings = mappings;
        this.extraActionsConfig = extraActionsConfig;// 默认actions
        this.defaultActionsConfig = _lodash2['default'].cloneDeep(DEFAULT_ACTIONS_CONFIG);// 用户配置actions
        this.actionsConfig = {};// 存储复合actions
        this.buildActionsConfig();// 获取复合actions并存储
    }

    // 添加ResourceConfig.prototype.buildActionsConfig原型方法,this.actionsConfig添加默认及用户配置的actions
    // 添加ResourceConfig.checkActionConfig静态方法,校验action的{url,params,method,isArray}配置
    //     如无url|method,赋值为_this.extraActionsConfig.url|method
    //     如无params,从_this.extraActionsConfig.url中解析得到
    //     如isArray为undfined或null,赋值为false
    _createClass(ResourceConfig, [{
        key: 'buildActionsConfig',
        value: function buildActionsConfig() {
            var _this = this;

            // HelpersAndParsers.uniqueArray数组项去重
            var mergedConfigKeys = HelpersAndParsers.uniqueArray(
                Object.keys(this.defaultActionsConfig).concat(Object.keys(this.extraActionsConfig))
            );
            _lodash2['default'].forEach(mergedConfigKeys, function (actionName) {
                // 默认及用户定义的action,{url,params,method,isArray}形式
                var defaultActionConfig = _this.defaultActionsConfig[actionName],
                    extraActionConfig = _this.extraActionsConfig[actionName];

                if (defaultActionConfig) _this.actionsConfig[actionName] = defaultActionConfig;

                if (extraActionConfig) {
                    _lodash2['default'].forEach(Object.keys(extraActionConfig), function (extraActionConfigKey) {
                        if (!_this.actionsConfig[actionName]) _this.actionsConfig[actionName] = {};
                        _this.actionsConfig[actionName][extraActionConfigKey] = extraActionConfig[extraActionConfigKey];
                    });
                }

                _this.checkActionConfig(actionName);
            });
        }
    }, {
        key: 'checkActionConfig',
        value: function checkActionConfig(actionName) {
            var actionConfig = this.actionsConfig[actionName];
            if (_lodash2['default'].isEmpty(actionConfig.url)) {
                this.actionsConfig[actionName].url = this.url;
            }
            if (_lodash2['default'].isEmpty(actionConfig.params)) {
                // HelpersAndParsers.extractQueryParams解析url中的查询字符串,对象形式输出
                this.actionsConfig[actionName].params = HelpersAndParsers.extractQueryParams(this.actionsConfig[actionName].url);
            }
            if (_lodash2['default'].isEmpty(actionConfig.method)) {
                this.actionsConfig[actionName].method = 'GET';
            }
            if (_lodash2['default'].isNull(actionConfig.isArray) || _lodash2['default'].isUndefined(actionConfig.isArray)) {
                this.actionsConfig[actionName].isArray = false;
            }
        }
    }]);

    return ResourceConfig;
})();

// 工具函数
var HelpersAndParsers = (function () {
    function HelpersAndParsers() {
        _classCallCheck(this, HelpersAndParsers);
    }

    // 添加静态方法
    // HelpersAndParsers.parseArgs获取本次请求的promiseConfig,形为{url,source,queryParams,bodyData,resolveFn,rejectFn}
    //      请求由resourceClass[actionName]发起
    // HelpersAndParsers.WithBodyData处理resourceClass[actionName]传参([source],[queryParams],[bodyData],[resolveFn],[rejectFn])
    //      ajax请求为类put形式,通过bodyData传输数据
    // HelpersAndParsers.NoBodyData处理resourceClass[actionName]传参([source],[queryParams],[resolveFn],[rejectFn])
    //      ajax请求为get形式,不通过bodyData传输数据
    //   resourceClass[actionName]即ReactResource(url,mapping,actionsConfig)[actionName]
    //   或new ReactResource(url,mapping,actionsConfig)["$"+actionName]
    // HelpersAndParsers.parseUrlWithMapping将首参actionConfig.url中变量{:id}替换为实际值或空
    // HelpersAndParsers.copyPureAttributes拷贝对象输出,"$"起始的键不拷贝
    // HelpersAndParsers.extractQueryParams解析url中的查询字符串,对象形式输出
    // HelpersAndParsers.uniqueArray数组项去重
    _createClass(HelpersAndParsers, null, [{
        key: 'parseArgs',

        // 获取本次请求的promiseConfig,形为{url,source,queryParams,bodyData,resolveFn,rejectFn}
        // 参数actionName是resourceConfig.actionsConfig中的键,参数resourceConfig即ResourceConfig实例
        // resourceConfig含url、mapping、actionsConfig属性,actionsConfig是默认及用户配置actions复合后的结果
        value: function parseArgs(actionName, resourceConfig) {
            var ModelInstance = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2];

            var promiseConfig = _lodash2['default'].cloneDeep(HelpersAndParsers.getDefaultPromiseConfig()),
                actionConfig = resourceConfig.actionsConfig && resourceConfig.actionsConfig[actionName],
                actionMethod = actionConfig && actionConfig.method.toUpperCase();

            // args接收从arguments第三项后的所有内容,不含第三项,即resourceClass[actionName]方法传参
            for (var _len2 = arguments.length, args = Array(_len2 > 3 ? _len2 - 3 : 0), _key2 = 3; _key2 < _len2; _key2++) {
                args[_key2 - 3] = arguments[_key2];
            }

            // actionname为'POST','PUT','PATCH','DELETE'及其小写形式
            if (ACTIONS_WITH_BODY.indexOf(actionMethod) > -1) {
                // HelpersAndParsers.WithBodyData处理resourceClass[actionName]传参args
                // 赋值给promiseConfig
                HelpersAndParsers.WithBodyData.apply(HelpersAndParsers, 
                    [actionName, resourceConfig, promiseConfig, ModelInstance].concat(args));

                // promiseConfig.source为空,promiseConfig.bodyData非空,promiseConfig.source和promiseConfig.bodyData等值
                if (!_lodash2['default'].isEmpty(promiseConfig.source) && _lodash2['default'].isEmpty(promiseConfig.bodyData)) {
                    HelpersAndParsers.copyPureAttributes(promiseConfig.source, promiseConfig.bodyData);
                }

            // actionname为'GET'及其小写形式
            } else if (ACTIONS_WITHOUT_BODY.indexOf(actionMethod) > -1) {
                // HelpersAndParsers.NoBodyData处理resourceClass[actionName]传参args
                // 赋值给promiseConfig
                HelpersAndParsers.NoBodyData.apply(HelpersAndParsers, [actionName, resourceConfig, promiseConfig, ModelInstance].concat(args));
            } else {
                throw Error("Dont know how to build HTTP request.", actionName, actionMethod);
            }

            // HelpersAndParsers.parseUrlWithMapping将首参actionConfig.url中变量{:id}替换为实际值或空
            promiseConfig.url = HelpersAndParsers.parseUrlWithMapping(actionConfig, resourceConfig, promiseConfig);
            return promiseConfig;
        }

    }, {
        key: 'WithBodyData',

        // resourceClass[actionName]传参处理([source],[queryParams],[bodyData],[resolveFn],[rejectFn])
        //      针对put形式的ajax,数据通过bodyData传递
        // 参数actionName是resourceConfig.actionsConfig中的键,参数resourceConfig即ResourceConfig实例
        // resourceConfig含url、mapping、actionsConfig属性,actionsConfig是默认及用户配置actions复合后的结果
        // 参数promiseConfigh是HelpersAndParsers.getDefaultPromiseConfig获取的默认promiseConfig
        value: function WithBodyData(actionName, resourceConfig, promiseConfig, ModelInstance) {
            // 用户调用形式为ReactResource(url,mapping,actionsConfig).get(...)为否,构造函数的静态方法
            // 用户调用形式为new ReactResource(url,mapping,actionsConfig).$get(...)为真,实例的原型链方法
            var isClassMethod = _lodash2['default'].isEmpty(ModelInstance);
            if (!isClassMethod) {
                promiseConfig.source = ModelInstance;
            }

            // args接收从arguments第四项后的所有内容,不含第四项,即resourceClass[actionName]方法传参
            for (var _len3 = arguments.length, args = Array(_len3 > 4 ? _len3 - 4 : 0), _key3 = 4; _key3 < _len3; _key3++) {
                args[_key3 - 4] = arguments[_key3];
            }

            switch (args.length) {
                case 5:
                    if (!isClassMethod) throw Error("Instance method can't have 5 arguments");
                    if (typeof args[0] == 'object' && typeof args[1] == 'object' && typeof args[2] == 'object' && typeof args[3] == 'function' && typeof args[4] == 'function') {
                        promiseConfig.source = args[0];
                        promiseConfig.queryParams = args[1];
                        promiseConfig.bodyData = args[2];
                        promiseConfig.resolveFn = args[3];
                        promiseConfig.rejectFn = args[4];
                    } else {
                        throw Error("Arguments types mismatch!");
                    }
                    break;
                case 4:
                    if (typeof args[0] == 'object' && typeof args[1] == 'object' && typeof args[2] == 'function' && typeof args[3] == 'function') {
                        if (isClassMethod) {
                            promiseConfig.source = args[0];
                            promiseConfig.queryParams = args[1];
                        } else {
                            promiseConfig.queryParams = args[0];
                            promiseConfig.bodyData = args[1];
                        }
                        promiseConfig.resolveFn = args[2];
                        promiseConfig.rejectFn = args[3];
                    } else if (typeof args[0] == 'object' && typeof args[1] == 'object' && typeof args[2] == 'object' && typeof args[3] == 'function') {
                        if (isClassMethod) {
                            promiseConfig.source = args[0];
                            promiseConfig.queryParams = args[1];
                            promiseConfig.bodyData = args[3];
                            promiseConfig.resolveFn = args[4];
                        } else {
                            throw Error("Arguments types mismatch!");
                        }
                    } else {
                        throw Error("Arguments types mismatch!");
                    }
                    break;
                case 3:
                    if (isClassMethod) {
                        promiseConfig.source = args[0];
                        if (typeof args[1] == 'function' && typeof args[2] == 'function') {
                            promiseConfig.resolveFn = args[1];
                            promiseConfig.rejectFn = args[2];
                        } else if (typeof args[1] == 'object' && typeof args[2] == 'function') {
                            promiseConfig.queryParams = args[1];
                            promiseConfig.rejectFn = args[2];
                        } else if (typeof args[1] == 'object' && typeof args[2] == 'object') {
                            promiseConfig.queryParams = args[1];
                            promiseConfig.bodyData = args[2];
                        } else {
                            throw Error("Arguments types mismatch!");
                        }
                    } else {
                        promiseConfig.queryParams = args[0];

                        if (typeof args[1] == 'object' && typeof args[2] == 'function') {
                          promiseConfig.bodyData = args[1];
                          promiseConfig.resolveFn = args[2];
                        } else if (typeof args[1] == 'function' && typeof args[2] == 'function') {
                            promiseConfig.resolveFn = args[1];
                            promiseConfig.rejectFn = args[2];
                        } else {
                            throw Error("Arguments types mismatch!");
                        }
                    }
                    break;
                case 2:
                    if (typeof args[0] == 'function' && typeof args[1] == 'function') {
                        promiseConfig.resolveFn = args[0];
                        promiseConfig.rejectFn = args[1];
                    } else {
                        if (isClassMethod) {
                            if (typeof args[0] == 'object' && typeof args[1] == 'function') {
                                promiseConfig.source = args[0];
                                promiseConfig.resolveFn = args[1];
                            } else if (typeof args[0] == 'object' && typeof args[1] == 'object') {
                                promiseConfig.source = args[0];
                                promiseConfig.queryParams = args[1];
                            } else {
                                throw Error("Arguments types mismatch!");
                            }
                        } else {
                            if (typeof args[0] == 'object' && typeof args[1] == 'function') {
                                promiseConfig.queryParams = args[0];
                                promiseConfig.resolveFn = args[1];
                            } else if (typeof args[0] == 'object' && typeof args[1] == 'object') {
                                promiseConfig.queryParams = args[0];
                                promiseConfig.bodyData = args[1];
                            } else {
                                throw Error("Arguments types mismatch!");
                            }
                        }
                    }
                    break;

                // resourceClass[actionName]传入单参数
                // 类层面调用时作为promiseConfig.source???,或promiseConfig.resolveFn成功时回调
                // 实例层面调用时作为promiseConfig.queryParams携带的查询数据,或promiseConfig.resolveFn成功时回调
                case 1:
                    if (typeof args[0] == 'object') {
                        if (isClassMethod) {
                            promiseConfig.source = args[0];
                        }else {
                            promiseConfig.queryParams = args[0];
                        }
                    } else {
                      if (typeof args[0] == 'function') {
                          promiseConfig.resolveFn = args[0];
                      } else {
                          throw Error("Arguments types mismatch!");
                      }
                    }
                    break;
            }
        }

    }, {
        key: 'NoBodyData',

        // resourceClass[actionName]传参处理([source],[queryParams],[resolveFn],[rejectFn])
        //      针对get形式的ajax,数据不通过bodyData传递
        // 参数actionName是resourceConfig.actionsConfig中的键,参数resourceConfig即ResourceConfig实例
        // resourceConfig含url、mapping、actionsConfig属性,actionsConfig是默认及用户配置actions复合后的结果
        // 参数promiseConfigh是HelpersAndParsers.getDefaultPromiseConfig获取的默认promiseConfig
        value: function NoBodyData(actionName, resourceConfig, promiseConfig, ModelInstance) {
            var isClassMethod = _lodash2['default'].isEmpty(ModelInstance),
                actionConfig = resourceConfig.actionsConfig[actionName];

            if (!isClassMethod) {
                promiseConfig.source = ModelInstance;
            }

            // args接收从arguments第四项后的所有内容,不含第四项,即resourceClass[actionName]方法传参
            for (var _len4 = arguments.length, args = Array(_len4 > 4 ? _len4 - 4 : 0), _key4 = 4; _key4 < _len4; _key4++) {
                args[_key4 - 4] = arguments[_key4];
            }

            switch (args.length) {
                case 4:
                    if (!isClassMethod) throw Error("Instance method can't have 4 arguments");
                    if (typeof args[0] == 'object' && typeof args[1] == 'object' && typeof args[2] == 'function' && typeof args[3] == 'function') {
                        promiseConfig.source = args[0];
                        promiseConfig.queryParams = args[1];
                        promiseConfig.resolveFn = args[2];
                        promiseConfig.rejectFn = args[3];
                    } else {
                        throw Error("Arguments types mismatch!");
                    }
                    break;
                case 3:
                    if (isClassMethod) {
                        if (typeof args[0] == 'object' && typeof args[1] == 'object' && typeof args[2] == 'function') {
                            promiseConfig.source = args[0];
                            promiseConfig.queryParams = args[1];
                            promiseConfig.resolveFn = args[2];
                        } else if (typeof args[0] == 'object' && typeof args[1] == 'function' && typeof args[2] == 'function') {
                            promiseConfig.source = args[0];
                            promiseConfig.resolveFn = args[1];
                            promiseConfig.rejectFn = args[2];
                        } else {
                            throw Error("Arguments types mismatch!");
                        }
                    } else {
                        if (typeof args[0] == 'object' && typeof args[1] == 'function' && typeof args[2] == 'function') {
                            promiseConfig.queryParams = args[0];
                            promiseConfig.resolveFn = args[1];
                            promiseConfig.rejectFn = args[2];
                        } else {
                            throw Error("Arguments types mismatch!");
                        }
                    }
                    break;
                case 2:
                    if (typeof args[0] == 'function' && typeof args[1] == 'function') {
                        promiseConfig.resolveFn = args[0];
                        promiseConfig.rejectFn = args[1];
                    } else {
                        if (isClassMethod) {
                            if (typeof args[0] == 'object' && typeof args[1] == 'object') {
                                promiseConfig.source = args[0];
                                promiseConfig.queryParams = args[1];
                            } else if (typeof args[0] == 'object' && typeof args[1] == 'function') {
                                promiseConfig.source = args[0];
                                promiseConfig.resolveFn = args[1];
                            } else {
                                throw Error("Arguments types mismatch!");
                            }
                        } else {
                            if (typeof args[0] == 'object' && typeof args[1] == 'function') {
                                promiseConfig.queryParams = args[0];
                                promiseConfig.resolveFn = args[1];
                            } else {
                                throw Error("Arguments types mismatch!");
                            }
                        }
                    }
                    break;
                case 1:
                    if (typeof args[0] == 'object') {
                        if (isClassMethod) {
                            if (actionConfig.isArray == false) {
                              promiseConfig.source = args[0];
                            } else {
                              promiseConfig.queryParams = args[0];
                            }
                        } else {
                            promiseConfig.queryParams = args[0];
                        }
                    } else if (typeof args[0] == 'function') {
                        promiseConfig.resolveFn = args[0];
                    } else {
                        throw Error("Arguments types mismatch!");
                    }
                    break;
            }
        }

    // actionConfig.url中变量{:id}替换为实际值或空
    }, {
      key: 'parseUrlWithMapping',
      value: function parseUrlWithMapping(actionConfig, resourceConfig, promiseConfig) {
          var outputUrl = _lodash2['default'].clone(actionConfig.url);
          for (var object_key in resourceConfig.mappings) {
              var sourceValue = promiseConfig.source[object_key];
              if (sourceValue) {
                  outputUrl = outputUrl.replace(new RegExp('{' + resourceConfig.mappings[object_key] + '}', 'g'), sourceValue);
              } else {
                  outputUrl = outputUrl.replace(new RegExp('/?{' + resourceConfig.mappings[object_key] + '}', 'g'), "");
              }
          }
          outputUrl = outputUrl.replace(/\/?\{\:.+\}/i, "");
          return outputUrl;
      }

    // 默认的promiseConfig,设置成功和失败时的回调函数
    // resourceClass[actionName]传参处理后将赋值给该promiseConfig拷贝,作为resourceClass[actionName]的promiseConfig
    }, {
      key: 'getDefaultPromiseConfig',
      value: function getDefaultPromiseConfig() {
          return {
              url: undefined,
              source: {},
              queryParams: {},
              bodyData: {},
              resolveFn: function resolveFn() {},
              rejectFn: function rejectFn() {}
          };
      }

    // 拷贝对象输出,"$"起始的键不拷贝
    }, {
      key: 'copyPureAttributes',
      value: function copyPureAttributes(sourceObject) {
          var targetObject = arguments.length <= 1 || arguments[1] === undefined ? {} : arguments[1];

          if (typeof sourceObject == 'object') {
              _lodash2['default'].forEach(Object.keys(sourceObject), function (sourceAttribute) {
                  // lodash.startsWith(str1,str2)校验str1是否以str2起始
                  if (_lodash2['default'].startsWith(sourceAttribute, '$') == false) {
                      targetObject[sourceAttribute] = sourceObject[sourceAttribute];
                  }
              });
          }
          return targetObject;
      }

    // 解析url中的查询字符串,对象形式输出
    }, {
      key: 'extractQueryParams',
      value: function extractQueryParams() {
          var inputUrl = arguments.length <= 0 || arguments[0] === undefined ? "" : arguments[0];

          var regex = /[?&]([^=#]+)=([^&#]*)/g,
              params = {},
              match = undefined;
          while (match = regex.exec(inputUrl)) {
              params[match[1]] = match[2];
          }
          return params;
      }

    // 数组项去重
    }, {
        key: 'uniqueArray',
        value: function uniqueArray() {
            var array = arguments.length <= 0 || arguments[0] === undefined ? [] : arguments[0];

            var a = array.concat();
            for (var i = 0; i < a.length; ++i) {
                for (var j = i + 1; j < a.length; ++j) {
                    if (a[i] === a[j]) a.splice(j--, 1);
                }
            }
            return a;
        }
    }]);

    return HelpersAndParsers;
})();

// 默认actions
var DEFAULT_ACTIONS_CONFIG = {
    'query': { url: null, params: {}, method: 'GET', isArray: true },
    'get': { url: null, params: {}, method: 'GET', isArray: false },
    'create': { url: null, params: {}, method: 'POST', isArray: false },
    'update': { url: null, params: {}, method: 'PUT', isArray: false },
    'delete': { url: null, params: {}, method: 'DELETE', isArray: false }
};

var ACTIONS_WITH_BODY = ['POST', 'PUT', 'PATCH', 'DELETE'];

var ACTIONS_WITHOUT_BODY = ['GET'];

module.exports = exports['default'];

 

 

0
0
分享到:
评论

相关推荐

    react-resource:用于React的角度资源的分叉

    8. **源码结构**:"react-resource-master"文件可能包含了项目的源代码、测试、文档和配置文件,用户可以直接克隆下来进行学习和定制。 为了充分利用这个库,开发者需要熟悉React的基本概念,包括组件、状态、props...

    react-resource:react源码分析,包括组件类,render()方法的源码-源码包

    在这个"react-resource:react源码分析"中,我们将深入探讨React组件类以及`render()`方法的源码。 首先,让我们来理解React组件。在React中,组件是JavaScript类,它们扩展了`React.Component`基类。组件可以接受...

    react-cli:create-react-app原始分析

    总结起来,`react-cli`是对`create-react-app`的一次学习与实践,通过对源码的解析,我们可以深入理解React应用的构建过程,提升自己的前端开发技能。同时,这样的实践也有助于我们更好地定制化项目,满足特定需求,...

    frontend-resource-源码.rar

    4. **前端框架和库**: 源码中可能使用了诸如React、Vue.js或Angular等流行前端框架,这些框架提供了高效的组件化开发方式,简化了状态管理、路由和生命周期管理。了解特定框架的API、生命周期方法和最佳实践对于阅读...

    ra-data-drf:一个使用Django REST Framework构建的后端的React-admin数据提供程序

    import { Admin , Resource } from 'react-admin' ; import drfProvider from 'ra-data-drf' ; import { UserList } from './users' ; const App = ( ) =&gt; ( &lt; Admin dataProvider = { drfProvider ( '...

    react-admin:react管理系统

    import { Admin, Resource } from 'react-admin'; import jsonServerProvider from 'ra-data-json-server'; const App = () =&gt; ( ('http://jsonplaceholder.typicode.com')}&gt; &lt;Resource name="users" list={User...

    react-admin:React Admin-ReactJS,Apollo GraphQL

    在"react-admin-master"这个压缩包中,包含了React Admin的源码,你可以深入研究其架构和实现细节。主要组件如`Admin`, `Resource`, `List`, `Show`, `Create`, `Edit`等,它们分别用于定义管理界面的基本结构、添加...

    计算机软件-商业源码-FitHRD.zip

    2. **人力资源管理**:HRD即Human Resource Development,FitHRD主要处理企业的人力资源流程,如招聘、培训、绩效评估、薪酬福利、员工关系等。它可能包含模块化的功能,以支持各个HR领域的高效运作。 3. **模块...

    JavaScript Applications with Node.js, React, React Native and MongoDB

    JavaScript Applications with Node.js, React, React Native and MongoDB: Design, code, test, deploy and manage in Amazon AWS By 作者: Eric Bush ISBN-10 书号: 0997196661 ISBN-13 书号: 9780997196665 出版...

    java版商城源码下载-web-resource:来自远方的&lt;>

    java版商城源码下载 :grinning_cat:These share data are from my usual work and learning,hoping to help you,If you like you can star It comes from chance encounters,if you like,you can follow ...

    UCRM-源码.rar

    UCRM,全称为User Connection Resource Management,是一种客户关系管理(Customer Relationship Management)系统,主要用于帮助企业更有效地管理和优化与客户的互动。源码通常是软件开发过程中的基础,它包含了...

    stardog_js-源码.rar

    Stardog 是一个强大的语义图数据库系统,它支持 RDF(Resource Description Framework)和其他语义数据模型,广泛应用于知识图谱、数据分析和智能应用程序等领域。Stardog_JS 的源码分析将帮助我们深入理解如何在 ...

    ltts_project-源码.rar

    不过,我们可以根据源码的上下文推测,可能涉及的标签有Java、Python、C++等编程语言,或者是Spring、Angular、React等开发框架。 【压缩包子文件的文件名称列表】:虽然未提供实际的文件列表,但在常见的项目结构...

    odssa-0_9_9-源码.rar

    2. **语义网技术**:语义网技术使ODSSA具有理解数据含义的能力,通过RDF(Resource Description Framework)、OWL(Web Ontology Language)等标准,实现了对数据的结构化表示和推理。这有助于实现更智能的信息检索...

    大型协同办公系统源码(OA+HR+CRM)源码.7z

    大型协同办公系统是一种集成化的管理软件,通常包括OA(Office Automation)办公自动化、HR(Human Resource)人力资源管理和CRM(Customer Relationship Management)客户关系管理等多个模块。这个源码压缩包提供了...

    blog-resource:博客分享的文章相关的代码合集,更多资源请关注公众号:IT平头哥联盟

    分享的文章相关源码 前端:html,css,javascript,canvas,小程序,react / vue等系列; 测试:自动化,性能,接口系列; 公众号: honeyBadger8 ; 资源:912594095,文章原始码的疑惑,小白入门前端/测试疑惑等; ...

    前端项目-i18next-xhr-backend.zip

    在实际项目中,配合i18next的其他插件和工具,如i18next-resource-store-backend(用于静态资源的本地存储)、react-i18next(针对React框架的集成),可以构建出完整的前端国际化解决方案。开发者需要注意的是,...

    Resource Online

    - 可能涵盖各种编程语言,如Java、Python、C++、JavaScript等,以及特定框架和库的源码,如Spring Boot、Django、React或Angular。 - 分析源码有助于提升编程技能,深入理解设计模式,以及如何实现高效、可维护的...

    dice评价指标matlab代码-awesome-why:资源收集

    Resource Collection 01 Deep Learning 中文翻译 | | | 02 Awesome lists about all kinds of interesting topics Awesome React Native is an awesome style list that curates the best React Native libraries, ...

Global site tag (gtag.js) - Google Analytics