UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

512 lines (436 loc) • 13.4 kB
"use strict"; var $ = require("../core/renderer"), dataUtils = require("./utils"), isFunction = require("../core/utils/type").isFunction, errors = require("./errors").errors, Store = require("./abstract_store"), arrayQuery = require("./array_query"), queryByOptions = require("./store_helper").queryByOptions, deferredUtils = require("../core/utils/deferred"), Deferred = deferredUtils.Deferred, when = deferredUtils.when, fromPromise = deferredUtils.fromPromise; var TOTAL_COUNT = "totalCount", LOAD = "load", BY_KEY = "byKey", INSERT = "insert", UPDATE = "update", REMOVE = "remove"; function isPromise(obj) { return obj && isFunction(obj.then); } function trivialPromise(value) { return new Deferred().resolve(value).promise(); } function ensureRequiredFuncOption(name, obj) { if (!isFunction(obj)) { throw errors.Error("E4011", name); } } function throwInvalidUserFuncResult(name) { throw errors.Error("E4012", name); } function createUserFuncFailureHandler(pendingDeferred) { function errorMessageFromXhr(promiseArguments) { var xhr = promiseArguments[0], textStatus = promiseArguments[1]; if (!xhr || !xhr.getResponseHeader) { return null; } return dataUtils.errorMessageFromXhr(xhr, textStatus); } return function (arg) { var error; if (arg instanceof Error) { error = arg; } else { error = new Error(errorMessageFromXhr(arguments) || arg && String(arg) || "Unknown error"); } if (error.message !== dataUtils.XHR_ERROR_UNLOAD) { pendingDeferred.reject(error); } }; } function invokeUserLoad(store, options) { var userFunc = store._loadFunc, userResult; ensureRequiredFuncOption(LOAD, userFunc); userResult = userFunc.apply(store, [options]); if (Array.isArray(userResult)) { userResult = trivialPromise(userResult); } else if (userResult === null || userResult === undefined) { userResult = trivialPromise([]); } else { if (!isPromise(userResult)) { throwInvalidUserFuncResult(LOAD); } } return fromPromise(userResult); } function invokeUserTotalCountFunc(store, options) { var userFunc = store._totalCountFunc, userResult; if (!isFunction(userFunc)) { throw errors.Error("E4021"); } userResult = userFunc.apply(store, [options]); if (!isPromise(userResult)) { userResult = Number(userResult); if (!isFinite(userResult)) { throwInvalidUserFuncResult(TOTAL_COUNT); } userResult = trivialPromise(userResult); } return fromPromise(userResult); } function invokeUserByKeyFunc(store, key, extraOptions) { var userFunc = store._byKeyFunc, userResult; ensureRequiredFuncOption(BY_KEY, userFunc); userResult = userFunc.apply(store, [key, extraOptions]); if (!isPromise(userResult)) { userResult = trivialPromise(userResult); } return fromPromise(userResult); } function runRawLoad(pendingDeferred, store, userFuncOptions, continuation) { if (store.__rawData) { continuation(store.__rawData); } else { invokeUserLoad(store, userFuncOptions).done(function (rawData) { if (store._cacheRawData) { store.__rawData = rawData; } continuation(rawData); }).fail(createUserFuncFailureHandler(pendingDeferred)); } } function runRawLoadWithQuery(pendingDeferred, store, options, countOnly) { options = options || {}; var userFuncOptions = {}; if ("userData" in options) { userFuncOptions.userData = options.userData; } runRawLoad(pendingDeferred, store, userFuncOptions, function (rawData) { var rawDataQuery = arrayQuery(rawData, { errorHandler: store._errorHandler }), itemsQuery, totalCountQuery, waitList = []; var items, totalCount; if (!countOnly) { itemsQuery = queryByOptions(rawDataQuery, options); if (itemsQuery === rawDataQuery) { items = rawData.slice(0); } else { waitList.push(itemsQuery.enumerate().done(function (asyncResult) { items = asyncResult; })); } } if (options.requireTotalCount || countOnly) { totalCountQuery = queryByOptions(rawDataQuery, options, true); if (totalCountQuery === rawDataQuery) { totalCount = rawData.length; } else { waitList.push(totalCountQuery.count().done(function (asyncResult) { totalCount = asyncResult; })); } } when.apply($, waitList).done(function () { if (countOnly) { pendingDeferred.resolve(totalCount); } else if (options.requireTotalCount) { pendingDeferred.resolve(items, { totalCount: totalCount }); } else { pendingDeferred.resolve(items); } }).fail(function (x) { pendingDeferred.reject(x); }); }); } function runRawLoadWithKey(pendingDeferred, store, key) { runRawLoad(pendingDeferred, store, {}, function (rawData) { var keyExpr = store.key(), item; for (var i = 0, len = rawData.length; i < len; i++) { item = rawData[i]; if (dataUtils.keysEqual(keyExpr, store.keyOf(rawData[i]), key)) { pendingDeferred.resolve(item); return; } } pendingDeferred.reject(errors.Error("E4009")); }); } /** * @name LoadOptions * @publicName LoadOptions * @namespace DevExpress.data * @type object */ /** * @name LoadOptions.filter * @publicName filter * @type object */ /** * @name LoadOptions.sort * @publicName sort * @type object */ /** * @name LoadOptions.select * @publicName select * @type object */ /** * @name LoadOptions.group * @publicName group * @type object */ /** * @name LoadOptions.skip * @publicName skip * @type number */ /** * @name LoadOptions.skip * @publicName skip * @type number */ /** * @name LoadOptions.take * @publicName take * @type number */ /** * @name LoadOptions.userData * @publicName userData * @type object */ /** * @name LoadOptions.expand * @publicName expand * @type object */ /** * @name LoadOptions.requireTotalCount * @publicName requireTotalCount * @type boolean */ /** * @name LoadOptions.searchValue * @publicName searchValue * @type any */ /** * @name LoadOptions.searchOperation * @publicName searchOperation * @type string */ /** * @name LoadOptions.searchExpr * @publicName searchExpr * @type getter|Array<getter> */ /** * @name LoadOptions.customQueryParams * @publicName customQueryParams * @type Object */ /** * @name LoadOptions.totalSummary * @publicName totalSummary * @type Object */ /** * @name LoadOptions.groupSummary * @publicName groupSummary * @type Object */ /** * @name LoadOptions.requireGroupCount * @publicName requireGroupCount * @type boolean */ /** * @name CustomStore * @publicName CustomStore * @inherits Store * @type object * @module data/custom_store * @export default */ var CustomStore = Store.inherit({ ctor: function ctor(options) { options = options || {}; this.callBase(options); /** * @name CustomStoreOptions.useDefaultSearch * @publicName useDefaultSearch * @type boolean * @default undefined */ this._useDefaultSearch = !!options.useDefaultSearch || options.loadMode === "raw"; /** * @name CustomStoreOptions.loadMode * @publicName loadMode * @type string * @default 'processed' * @acceptValues 'processed'|'raw' */ this._loadMode = options.loadMode; /** * @name CustomStoreOptions.cacheRawData * @publicName cacheRawData * @type boolean * @default true */ this._cacheRawData = options.cacheRawData !== false; /** * @name CustomStoreOptions.load * @publicName load * @type function * @type_function_param1 options:LoadOptions * @type_function_return Promise<any> */ this._loadFunc = options[LOAD]; /** * @name CustomStoreOptions.totalCount * @publicName totalCount * @type function * @type_function_param1 loadOptions:object * @type_function_param1_field1 filter:object * @type_function_param1_field2 group:object * @type_function_return Promise<number> */ this._totalCountFunc = options[TOTAL_COUNT]; /** * @name CustomStoreOptions.byKey * @publicName byKey * @type function * @type_function_param1 key:object|string|number * @type_function_return Promise<any> */ this._byKeyFunc = options[BY_KEY]; /** * @name CustomStoreOptions.insert * @publicName insert * @type function * @type_function_param1 values:object * @type_function_return Promise<any> */ this._insertFunc = options[INSERT]; /** * @name CustomStoreOptions.update * @publicName update * @type function * @type_function_param1 key:object|string|number * @type_function_param2 values:object * @type_function_return Promise<any> */ this._updateFunc = options[UPDATE]; /** * @name CustomStoreOptions.remove * @publicName remove * @type function * @type_function_param1 key:object|string|number * @type_function_return Promise<void> */ this._removeFunc = options[REMOVE]; }, createQuery: function createQuery() { throw errors.Error("E4010"); }, /** * @name CustomStoreMethods.clearRawDataCache * @publicName clearRawDataCache() */ clearRawDataCache: function clearRawDataCache() { delete this.__rawData; }, _totalCountImpl: function _totalCountImpl(options) { var d = new Deferred(); if (this._loadMode === "raw" && !this._totalCountFunc) { runRawLoadWithQuery(d, this, options, true); } else { invokeUserTotalCountFunc(this, options).done(function (count) { d.resolve(Number(count)); }).fail(createUserFuncFailureHandler(d)); d = this._addFailHandlers(d); } return d.promise(); }, _loadImpl: function _loadImpl(options) { var d = new Deferred(); if (this._loadMode === "raw") { runRawLoadWithQuery(d, this, options, false); } else { invokeUserLoad(this, options).done(function (data, extra) { d.resolve(data, extra); }).fail(createUserFuncFailureHandler(d)); d = this._addFailHandlers(d); } return d.promise(); }, _byKeyImpl: function _byKeyImpl(key, extraOptions) { var d = new Deferred(); if (this._byKeyViaLoad()) { this._requireKey(); runRawLoadWithKey(d, this, key); } else { invokeUserByKeyFunc(this, key, extraOptions).done(function (obj) { d.resolve(obj); }).fail(createUserFuncFailureHandler(d)); } return d.promise(); }, _byKeyViaLoad: function _byKeyViaLoad() { return this._loadMode === "raw" && !this._byKeyFunc; }, _insertImpl: function _insertImpl(values) { var userFunc = this._insertFunc, userResult, d = new Deferred(); ensureRequiredFuncOption(INSERT, userFunc); userResult = userFunc.apply(this, [values]); // should return key only if (!isPromise(userResult)) { userResult = trivialPromise(userResult); } fromPromise(userResult).done(function (newKey) { d.resolve(values, newKey); }).fail(createUserFuncFailureHandler(d)); return d.promise(); }, _updateImpl: function _updateImpl(key, values) { var userFunc = this._updateFunc, userResult, d = new Deferred(); ensureRequiredFuncOption(UPDATE, userFunc); userResult = userFunc.apply(this, [key, values]); if (!isPromise(userResult)) { userResult = trivialPromise(); } fromPromise(userResult).done(function () { d.resolve(key, values); }).fail(createUserFuncFailureHandler(d)); return d.promise(); }, _removeImpl: function _removeImpl(key) { var userFunc = this._removeFunc, userResult, d = new Deferred(); ensureRequiredFuncOption(REMOVE, userFunc); userResult = userFunc.apply(this, [key]); if (!isPromise(userResult)) { userResult = trivialPromise(); } fromPromise(userResult).done(function () { d.resolve(key); }).fail(createUserFuncFailureHandler(d)); return d.promise(); } }); module.exports = CustomStore;